簡體   English   中英

如何在plpgsql中使用記錄類型變量?

[英]How to use a record type variable in plpgsql?

如何將存儲在記錄類型變量中的查詢結果用於同一存儲的 function 中的另一個查詢? 我使用 Postgres 9.4.4。

使用這樣的表:

create table test (id int, tags text[]);
insert into test values (1,'{a,b,c}'),
                        (2,'{c,d,e}');

我寫了一個 function(簡體),如下所示:

CREATE OR REPLACE FUNCTION func(_tbl regclass)
RETURNS TABLE (t TEXT[], e TEXT[])
LANGUAGE plpgsql AS $$
DECLARE
  t RECORD;
  c INT;
BEGIN
  EXECUTE format('SELECT id, tags FROM %s', _tbl) INTO t;
  SELECT count(*) FROM t INTO c;
  RAISE NOTICE '% results', c;
  SELECT * FROM t;
END
$$;

...但沒有用:

select func('test');
 ERROR: 42P01: relation "t" does not exist LINE 1: SELECT count(*) FROM t ^ QUERY: SELECT count(*) FROM t CONTEXT: PL/pgSQL function func(regclass) line 7 at SQL statement LOCATION: parserOpenTable, parse_relation.c:986

核心誤解: record變量包含單行 (或為NULL),而不是表(0-n行的已知類型)。 Postgres或PL / pgSQL沒有“表變量” 根據任務的不同,有各種替代方案:

因此,您不能將行分配給record類型變量。 在這個聲明中:

EXECUTE format('SELECT id, tags FROM %s', _tbl) INTO t;

... Postgres 分配第一行並丟棄其余部分。 由於“第一個”在您的查詢中沒有很好地定義,因此您最終會選擇一個任意選擇。 顯然是由於一開始就提到的誤解。

record變量也不能用於代替SQL查詢中的表。 這是導致錯誤的主要原因:

關系“t”不存在

現在應該很清楚, count(*)開頭沒有任何意義,因為t只是一個記錄/行 - 除此之外不可能。

最后(即使其余的工作),你的返回類型似乎是錯誤的: (t TEXT[], e TEXT[]) 因為你選擇id, tagst ,你想要返回類似(id int, e TEXT[])

你想要做的是這樣的

CREATE OR REPLACE FUNCTION func(_tbl regclass)
  RETURNS TABLE (id int, e text[]) AS
$func$
DECLARE
   _ct int;
BEGIN
   EXECUTE format(
      'CREATE TEMP TABLE tmp ON COMMIT DROP AS
       SELECT id, tags FROM %s'
    , _tbl);

   GET DIAGNOSTICS _ct = ROW_COUNT; -- cheaper than another count(*)

   -- ANALYZE tmp;  -- if you are going to run multiple queries

   RAISE NOTICE '% results', _ct;

   RETURN QUERY TABLE tmp;
END
$func$ LANGUAGE plpgsql;

調用(注意語法!)

SELECT * FROM func('test');

有關:

只是一個概念證明。 在選擇整個表時,您只需使用基礎表。 實際上,你在查詢中會有一些WHERE子句......

注意潛伏類型不匹配, count()返回bigint ,你不能將它分配給integer變量。 需要一個強制轉換: count(*)::int

但是我完全取代了它,在EXECUTE之后運行它會更便宜:

GET DIAGNOSTICS _ct = ROW_COUNT; 

手冊中的詳細信息。

為何ANALYZE


另外:普通SQL中的CTE通常可以完成這項工作:

以下是我在 redshift 數據庫的 plpgsql 中使用 RECORD 類型變量的幾種方法

  1. 運行一個循環
  2. 存儲記錄變量

代碼類型 1

    SOME BOILERPLATE

    $body$
    declare 
    
    arow record ;
    
    begin 
    for arow in ({table})    -- use of record type
      loop
      update #some_table 
        
       column1_some_table := arow.column1,
       column2_some_table := arow.column2 
       where some_condition
      
      end loop ; 
   end ;
   $body$;
  

代碼類型 2

    SOME BOILERPLATE

    $body$
    declare 
    
    arow record ;
    
    begin 
    while (counter <= max_counter)
    loop
    select column1, column2 into arow   -- use of record type
      from {table}
      update #some_table 
        
       column1_some_table := arow.column1,
       column2_some_table := arow.column2 
       where some_condition
      counter = counter+1
      end loop ; 
   end ;
   $body$;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM