我有一个 pl/pgsql 函数(见下文),它列出了一些字段并使用动态构造的 UPDATE 命令清除它们的内容。
当我设置时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;
问的问题
有一种内置方法可以记录 plpgsql 函数中的所有语句:
auto-explain
这个密切相关的问题下的详细信息:
用 pgpsql 编写的 UDF 调用的 Postgres 查询计划
可能会产生大量的日志输出。我只会将它用于调试,而不是在生产中。
如果您只需要记录一个语句,请遵循@dezso 的建议。
代码审计
考虑这个重写的函数:
要点
您必须清理构建到动态 SQL 中的所有标识符,否则它可能会因需要双引号的非标准名称而失败。更糟糕的是,您对 SQL 注入持开放态度。
演示
quote_ident()
,因为您多次使用经过清理的标识符。有更多选项regclass
orformat()
:表名作为 PostgreSQL 函数参数
我更喜欢将此类查询基于系统目录,而不是信息模式的缓慢视图。不过,这是需求和品味的问题。演示等价物,大约快 10 倍(与
UPDATE
命令无关)。更多:如何检查给定模式中是否存在表
LIKE
通常比更强大的正则表达式匹配 (~
) 更快。如果LIKE
可以完成这项工作,请使用它。其他一些小的简化。
更多详细信息的相关答案:
更新表名是参数的游标记录
所以,我的建议是一个实际的答案:
如果您仅在此函数中需要它,则可以执行
RAISE LOG '%', your_statement;
, 或在您的实际代码中:另外,我发现
构造更平滑。
伟大的 dezso,它的工作原理!这是我的函数的最终版本: