0

Redshiftからスキーマ内のオブジェクトのリストを取得する関数を作成しようとしています。私はRDS PostgreSQLからRedshiftへのdblinkを作成しました。クエリは個別に呼び出されたときにうまく動作しますが、引数を持つ関数の内部に記述されているときは機能しません。私は複数の引数(スキーマ名)を渡したいので、VARIADIC引数を使用しました。関数は以下のように見える -Postgresql関数 - テキスト型の可変引数を使用

CREATE FUNCTION f_fetch_tables(VARIADIC list text[]) 
RETURNS VOID 
AS $$ 
    DECLARE 
     begin_time TIMESTAMP; 
     expire_time TIMESTAMP; 
    BEGIN 
     /* To fetch the list of all objects from Redshift */ 
     EXECUTE 'drop table if exists tmp_rs_obj_list; 
     create table tmp_rs_obj_list as 
     SELECT * FROM dblink(''rs_link'',$REDSHIFT$ select * from (select schemaname, 
     tablename from pg_tables UNION select schemaname, viewname from pg_views) where schemaname 
     not in (array_to_string($1,'','')) $REDSHIFT$) AS t1 (schema_nm varchar(30), obj_nm varchar(100))' using list; 
    END; 
    $$ 
    LANGUAGE plpgsql 
; 

機能は罰金コンパイルし、正常に作成されたが、私はそれを呼び出す方法を把握することはできませんよ -

は運なしで、これまでにこれらの呼び出しを使用します -

  1. 選択f_fetch_tables( '{公共、pg_catalogの}')

    ERROR:エラーがデータベース・リンク接続に発生しました:パラメータがない場合は$ 1 "unnamed"という名前の: クエリを実行できませんでした。

  2. はf_fetch_tables(VARIADIC '{公共、pg_catalogの}')SELECT * FROM

    ERROR:何のパラメータは$ 1 どこにありません:エラーは、 "無名の" という名前のデータベース・リンク接続で発生しました:クエリを実行できませんでした。

ご意見は本当に役に立ちます。

は、この問題は、可変長のパラメータに関連していない、 Kamlesh

答えて

2

機能にはいくつか問題があります。私が使用することをお勧め:

  • 機能format()パラメータを渡す簡単にするために、
  • ドルが代わりにnot inオペレータのexecute
  • <> all(array)($fmt$)クエリを引用します(文字列に配列を変換する必要はありません。 )。
  • 提案された変更と

機能:

create or replace function f_fetch_tables(variadic list text[]) 
returns void 
as $$ 
    declare 
     begin_time timestamp; 
     expire_time timestamp; 
    begin 
     /* to fetch the list of all objects from redshift */ 
     execute format($fmt$ 
      drop table if exists tmp_rs_obj_list; 
      create table tmp_rs_obj_list as 
       select * 
       from dblink(
        'rs_link', $redshift$ 
         select * 
         from (
          select schemaname, tablename 
          from pg_tables 
          union 
          select schemaname, viewname 
          from pg_views) s 
         where schemaname <> all(%L) 
        $redshift$) 
        as t1 (schema_nm varchar(30), obj_nm varchar(100)) 
      $fmt$, list); 
    end; 
$$ 
language plpgsql; 

も注意可変引数パラメータで関数に引数を渡す正しい方法:

select f_fetch_tables('pg_catalog', 'information_schema'); 
select * from tmp_rs_obj_list; 
+0

は@klinありがとうございます。これは私のために働いた..! –

0

をありがとう - 同じあなたも通常のパラメータを使用する場合は取得します振る舞います。動的SQLに関連しています.PLpgSQLのEXECUTEコマンドが実行するクエリには、独自のパラメータ環境があります。したがって、関数の環境から変数やパラメータ参照を使用することはできません。

このコードは動作しません:

CREATE OR REPLACE FUNCTION fx(a int) 
RETURNS void AS $$ 
BEGIN 
    EXECUTE 'SELECT * FROM foo WHERE foo.a = $1'; 
END; 
$$ LANGUAGE plpgsql; 

をこの場合、実行されたクエリに任意のパラメータが渡されていませんでした。 $1は無効です。一部のパラメータを動的SQLに渡す場合は、USING句を使用する必要があります。

このコードが動作するようにすべきである:

CREATE OR REPLACE FUNCTION fx(a int) 
RETURNS void AS $$ 
BEGIN 
    EXECUTE 'SELECT * FROM foo WHERE foo.a = $1' USING a; 
END; 
$$ LANGUAGE plpgsql; 

をしかし、あなたはUSING句を使用しているので、それは、あまりにもあなたの問題を解決するためにはありません。しかし、レベルEXECUTEのコマンドでUSING句を使用しています - dblinkレベルではありません - サポートされていないレベルです。 dblink APIには、USING句のEXECUTEコマンドと似たものはありません。したがって、dblink APIに送信する前に、アンパックされた(事前評価された)パラメータを持つネイティブSQL文字列を作成する必要があります。あなたは、動的SQLの二つのレベルを使用している

  • EXECUTE
    • dblink

dblinkクエリパラメータ化をサポートしていません - あなたは、パラメータの場所を使用するべきではありません$ x。

この場合、入力配列をトップplpgsqlレベルの文字列にシリアル化し、動的SQLパラメータのようにこの文字列を渡す方が良いです。

DECLARE serialized_params text; 
BEGIN 
    serialized_params = (SELECT array_agg(quote_literal(quote_ident(v))) FROM unnest(ARRAY['A','b']) g(v)); 
    EXECUTE ' ....' USING serialized_params; 
END 
関連する問題