在我的数据库中,我有标准的应用程序表和备份表。例如,对于表“employee”,我有一个名为“巴克_employee”的表。巴克_employee表是employee表的备份。我用它来在测试之间还原employee表。
我想我可以使用这些“巴克_”表来查看在测试期间发生的更改,如下所示:
SELECT * FROM employee EXCEPT SELECT * FROM bak_employee
这将显示插入和更新的记录。我暂时忽略已删除的记录。
现在,我想做的是遍历数据库中的所有表,看看是否有任何表中的任何更改。我想把它作为一个函数来做,这样就很容易一遍又一遍地调用。这是我目前掌握的情况:
CREATE OR REPLACE FUNCTION public.show_diff()
RETURNS SETOF diff_tables AS
$BODY$
DECLARE
app_tables text;
BEGIN
FOR app_tables IN
SELECT table_name
FROM information_schema.tables
WHERE table_catalog = 'myDatabase'
AND table_schema = 'public'
AND table_name not like 'bak_%' -- exclude existing backup tables
LOOP
-- somehow loop through tables to see what's changed something like:
EXECUTE 'SELECT * FROM ' || app_tables || ' EXCEPT SELECT * FROM bak_' || app_tables;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql;
但显然这不会给我任何有用的信息。任何帮助将不胜感激。
1条答案
按热度按时间rsl1atfo1#
不能在同一调用中从同一函数返回不同的已知行类型。一个便宜的修复方法是将每个行类型强制转换为
text
,这样我们就有了一个通用的返回类型:电话:
一开始我有@a_horse建议的测试,但在你的评论之后,我意识到没有必要这样做。
EXCEPT
认为NULL
的值 * 相等 *,并显示 * 所有 * 差异。同时,我改进并简化了您的解决方案。使用
EXCEPT ALL
:更便宜并且不会冒折叠完整副本的风险。TABLE
只是语法糖。参见:然而,如果你有一个唯一列(组合)的索引,像我之前建议的
JOIN
应该更快:通过索引找到唯一可能的副本应该相当便宜。关键元素是将行类型转换为
text
(x::text
)。你甚至可以让这个函数对任何表都起作用,但一次不能超过一个:使用多态参数类型: