Man*_*bes 5 postgresql partitioning plpgsql
我有一个分区表,其中数据仅驻留在子表中。主表有一个插入触发器,可以将插入的数据分配到适当的子表中。
现在,我需要创建一个 PL/pgSQL 过程,该过程从(主)表中选择一些数据并使用一些更改的值重新插入它。
通常我会使用ROW_COUNT诊断变量并完成它。问题是 ROW_COUNT 始终为 0,因为主表中没有插入任何内容(触发器在途中捕获并重定向插入)。
我的下一个想法是做类似的事情
WITH inserted AS (
INSERT INTO master (...) SELECT ... FROM master WHERE ... RETURNING master.field
) SELECT count(*) FROM inserted INTO rowcount;
Run Code Online (Sandbox Code Playgroud)
但是,再次,rowcount 总是最终为 0,因为没有实际插入到主表中。
如果我做
WITH insertable AS (
SELECT ... FROM master WHERE ...
), blah AS (
SELECT count(*) INTO rowcount FROM insertable
) INSERT INTO master SELECT * FROM insertable;
Run Code Online (Sandbox Code Playgroud)
然后 Postgresql 抱怨说:
错误:INTO 与无法返回数据的命令一起使用
SQL 状态:42601
等等...
如果是我最后的代码提取,我如何将行数inserted放入rowcount我的程序中的变量中,然后我可以用它来做东西™?或者有没有其他方法可以检索插入到(继承自)主表中的行数?
如果这对您来说仍然是理想的(尽管不是那么重要),那么这是一个解决方案:
CREATE TABLE rows_affected_in_session (
session_pid int NOT NULL,
session_time timestamptz NOT NULL,
table_name text NOT NULL,
rows_affected int NOT NULL,
PRIMARY KEY (session_pid, session_time, table_name));
CREATE OR REPLACE FUNCTION f_update_rows_affected_in_session (p_table regclass, p_rows_affected int) RETURNS void AS $BODY$
BEGIN
IF NOT EXISTS (SELECT 1 FROM rows_affected_in_session WHERE session_pid = pg_backend_pid() AND session_time = current_timestamp AND table_name = p_table::text) THEN
INSERT INTO rows_affected_in_session (session_pid, session_time, table_name, rows_affected)
VALUES (pg_backend_pid(), current_timestamp, p_table::text, p_rows_affected);
ELSE
UPDATE rows_affected_in_session SET rows_affected = rows_affected + p_rows_affected
WHERE session_pid = pg_backend_pid() AND session_time = current_timestamp AND table_name = p_table::text;
END IF;
END;
$BODY$ LANGUAGE PLPGSQL SECURITY DEFINER;
CREATE OR REPLACE FUNCTION f_rows_affected_in_session() RETURNS TABLE (table_name text, rows_affected int) AS $BODY$
SELECT table_name, rows_affected
FROM rows_affected_in_session
WHERE session_pid = pg_backend_pid() AND session_time = current_timestamp
ORDER BY 1
$BODY$ LANGUAGE SQL SECURITY DEFINER;
Run Code Online (Sandbox Code Playgroud)
f_update_rows_affected_in_session(<table>, <rows_affected>)您可以通过在触发器中每次成功插入后调用该函数来使用它(您可以使用 ROW_COUNT 诊断),然后使用该函数f_rows_affected_in_session()检索会话中受影响的行(您可以在其中准确确定哪些子表受到影响,或者求和总计结果)。例子:
SELECT f_update_rows_affected_in_session('mytable'::regclass, 1);
SELECT f_update_rows_affected_in_session('mytable'::regclass, 1);
SELECT f_update_rows_affected_in_session('mytable'::regclass, 1);
SELECT * FROM f_rows_affected_in_session();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2942 次 |
| 最近记录: |