いくつかのフィールドをリストし、動的に構築されたUPDATEコマンドを使用してそれらの内容をクリアするpl/pgsql関数(以下を参照)があります。
_log_statement = 'mod'
_を設定すると、SELECT fnct_clear_temp_fields();
を使用して関数を実行しても、ログに何も表示されません。 _log_statement = 'all'
_を設定して関数を実行すると、ログにSELECT fnct_clear_temp_fields();
が表示されますが、基になるUPDATEコマンドは表示されません。
UPDATEコマンドもログに表示する方法はありますか?
参考までに、ここに関数があります:
_CREATE OR REPLACE FUNCTION fnct_clear_temp_fields() RETURNS VOID AS $$
DECLARE
--Put into a cursor a view dynamically listing all user-defined fields beginning with 'temp_'
dataset_1 CURSOR FOR
SELECT
column_name,
table_name
FROM information_schema.tables
NATURAL JOIN information_schema.columns
WHERE
table_schema='public'
AND table_type='BASE TABLE'
AND column_name ~ '^temp_'
ORDER BY table_name,column_name;
--Record variable to go through each line of the view above
dataset_1_row RECORD;
BEGIN
OPEN dataset_1; --Open the cursor
FETCH dataset_1 INTO dataset_1_row; --first row of the view
WHILE FOUND LOOP
RAISE NOTICE 'Table: %, Column: %', dataset_1_row.table_name,dataset_1_row.column_name;
--Set to NULL the contents of the current 'temp_' column
EXECUTE 'UPDATE '||dataset_1_row.table_name||' SET '||dataset_1_row.column_name||'=NULL WHERE '||dataset_1_row.column_name||' IS NOT NULL';
FETCH dataset_1 INTO dataset_1_row; --next row please.
END LOOP; --while end
CLOSE dataset_1;
RETURN;
END;
$$ LANGUAGE plpgsql;
_
だから、実際の答えとしての私の提案:
この関数でのみ必要な場合は、RAISE LOG '%', your_statement;
、または実際のコード:
...
DECLARE
exec_str text;
...
--Set to NULL the contents of the current 'temp_' column
exec_str := 'UPDATE '||dataset_1_row.table_name||
'SET '||dataset_1_row.column_name||'=NULL
WHERE '||dataset_1_row.column_name||' IS NOT NULL';
RAISE LOG 'Query executed: %', exec_str;
EXECUTE exec_str;
...
また、私は見つけます
FOR dataset_1_row IN SELECT ...
LOOP
END LOOP;
よりスムーズに構築します。
そこにisplpgsql関数内のすべてのステートメントを記録する組み込みの方法があります:_auto-explain
_
_LOAD 'auto_explain';
SET auto_explain.log_min_duration = 1; -- exclude very fast trivial queries
SET auto_explain.log_nested_statements = ON; -- statements inside functions
_
この密接に関連した質問の詳細:
pgpsqlで記述されたUDF呼び出しのPostgresクエリプラン
潜在的に大量のログ出力を生成します。本番環境ではなく、デバッグにのみ使用します。
1つのステートメントだけを記録する必要がある場合は、 @ dezsoのアドバイス を使用してください。
この書き換えられた関数を考えてみましょう:
_CREATE OR REPLACE FUNCTION fnct_clear_temp_fields()
RETURNS void AS
$func$
DECLARE
rec record;
qry text;
BEGIN
FOR rec IN
SELECT quote_ident(c.relname) AS tbl, quote_ident(a.attname) AS col
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE n.nspname = 'public'
AND c.relkind = 'r'
AND a.attname LIKE 'temp_%' -- LIKE is faster than ~
AND a.attnum > 0
AND NOT a.attisdropped
ORDER BY 1,2
LOOP
RAISE NOTICE 'Table: %, Column: %', rec.tbl, rec.col;
qry := format('UPDATE %1$s SET %2$s = NULL WHERE %2$s IS NOT NULL', rec.tbl, rec.col);
RAISE LOG 'Query: %', qry;
EXECUTE qry;
END LOOP;
END
$func$ LANGUAGE plpgsql;
_
動的SQLに構築するすべての識別子をサニタイズするmustさもなければ、非標準で失敗する可能性があります二重引用符が必要な名前。さらに悪いことに、SQLインジェクションを受け入れる可能性があります。
デモンストレーション quote_ident()
、サニタイズされた識別子を複数回使用しているため。 regclass
または format()
にはさらにオプションがあります:
PostgreSQL関数パラメーターとしてのテーブル名
情報スキーマの非常に遅いビューではなく、システムカタログに基づいてこのようなクエリを行うことを好みます。ただし、それは要件と好みの問題です。同等のものを示しており、これは約10倍高速です(UPDATE
コマンドは関係ありません)。もっと:
特定のスキーマにテーブルが存在するかどうかを確認する方法
LIKE
は通常、より強力な正規表現マッチング(_~
_)よりも高速です。 LIKE
がその仕事をできるなら、それを使ってください。
他のいくつかのマイナーな簡略化。
詳細と関連する回答:
テーブル名がパラメータであるカーソルの更新レコード
素晴らしいdezso、それはうまくいきます!これが私の関数の最終バージョンです:
CREATE OR REPLACE FUNCTION fnct_clear_temp_fields() RETURNS VOID AS $$
DECLARE
dataset_1_row RECORD; --Record variable to go through each row of the view below
update_query TEXT; --The dynamic UPDATE query to be executed
BEGIN
FOR dataset_1_row IN --Cycle through rows of query below
SELECT
column_name,
table_name
FROM information_schema.tables
NATURAL JOIN information_schema.columns
WHERE
table_schema='public'
AND table_type='BASE TABLE'
AND column_name ~ '^temp_'
ORDER BY table_name,column_name
LOOP
RAISE NOTICE 'Table: %, Column: %', dataset_1_row.table_name,dataset_1_row.column_name;
--Create a dynamic update query to set to NULL the contents of the current 'temp_' column
update_query :='UPDATE '||dataset_1_row.table_name||' SET '||dataset_1_row.column_name||'=NULL WHERE '||dataset_1_row.column_name||' IS NOT NULL;';
RAISE LOG 'Query executed: %', update_query; --Put query def in log
EXECUTE update_query; --Run the query
END LOOP; --Next line of SELECT query above
RETURN;
END;
$$ LANGUAGE plpgsql;