0

データベース内の複数のテーブルからフィールド値を取得する関数を作成しようとしています。次のようなスクリプトを作成しました。

CREATE OR REPLACE FUNCTION get_all_changes() RETURNS SETOF RECORD AS
$$
DECLARE 
  tblname VARCHAR;
  tblrow RECORD;
  row RECORD;
BEGIN
    FOR tblrow IN SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname='public' LOOP /*FOREACH tblname IN ARRAY $1 LOOP*/
      RAISE NOTICE 'r: %', tblrow.tablename;
      FOR row IN SELECT MAX("lastUpdate") FROM tblrow.tablename LOOP
          RETURN NEXT row;
      END LOOP;
    END LOOP;
END
$$
LANGUAGE 'plpgsql' ;

SELECT get_all_changes();

しかし、このエラーが表示されるたびに機能していません

tblrow.tablename" not defined in line "FOR row IN SELECT MAX("lastUpdate") FROM tblrow.tablename LOOP"
4

3 に答える 3

0

新しい質問への回答 (回答として誤ってラベル付けされています):

これははるかに簡単です。レコード タイプを定義するだけで、テーブルを作成する必要はありません。あるとしても、 を使用してタイプを作成する方がよいでしょうがCREATE TYPE、それは複数の場所でタイプが必要な場合にのみ効率的です。単一の関数については、RETURNS TABLE代わりに次を使用できます。

CREATE OR REPLACE FUNCTION get_all_changes(text[])
 RETURNS TABLE (tablename text
               ,"lastUpdate" timestamp with time zone
               ,nums integer) AS
$func$
DECLARE 
    tblname text;
BEGIN
    FOREACH tblname IN ARRAY $1 LOOP
        RETURN QUERY EXECUTE format(
        $f$SELECT '%I', MAX("lastUpdate"), COUNT(*)::int FROM %1$I
        $f$, tblname)
    END LOOP;
END
$func$ LANGUAGE plpgsql;

さらにいくつかのポイント:

  • RETURN QUERY EXECUTEネストされたループの代わりに使用します。はるかに簡単で高速です。

  • 列のエイリアスはドキュメントとしてのみ機能し、それらの名前は破棄され、RETURNS句で宣言された名前が優先されます (直接的または間接的に)。

  • format()withを使用し%Iて連結を置き換え、同じパラメータを別の機会に参照します。quote_ident()%1$I

  • count()通常は type を返しますbigint。戻り値の型で列を次のように定義したため、整数をキャストしますcount(*)::int

于 2013-05-12T19:12:46.323 に答える