PL/PGSQL 架构中所有表的动态触发器
PL/PGSQL dynamic trigger for all tables in schema
我希望通过自动更新 updated_at 列来自动执行每个 table 更新。我可以使用触发器为特定的 table 完成这项工作。但是我在任何地方都找不到的主要目标是创建一个函数,该函数动态获取模式中的所有 table,并创建相同的触发器,并且只更改 table 名称触发器正在引用。对于我的生活,我无法弄清楚。
我相信这不应该像我所做的那样棘手,因为我们的架构中的 table 将具有完全相同的列名称 'updated_at'。
我尝试过并认为可行的一个解决方案是将 table 模式转换为数组,并在每次迭代中迭代到 invoke/create 触发器。但是我没有大量的 psql 经验,所以我发现自己在谷歌上搜索了几个小时来解决这件小事。
SELECT ARRAY (
SELECT
table_name::text
FROM
information_schema.tables
WHERE table_schema = 'public') as tables;
我也试过:
DO $$
DECLARE
t text;
BEGIN
FOR t IN
SELECT table_name FROM information_schema.columns
WHERE column_name = 'updated_at'
LOOP
EXECUTE format('CREATE TRIGGER update_updatedAt
BEFORE UPDATE ON %I
FOR EACH ROW EXECUTE PROCEDURE updated_at()',
t);
END loop;
END;
$$ language 'plpgsql';
程序:
CREATE OR REPLACE FUNCTION updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
您的 DO
块有效。唯一的问题是我们不能为多个触发器使用相同的触发器名称。因此,您可以为触发器名称添加 table_name suffix/prefix。
DO $$
DECLARE
t text;
BEGIN
FOR t IN
SELECT table_name FROM information_schema.columns
WHERE column_name = 'updated_at'
LOOP
EXECUTE format('CREATE TRIGGER update_updatedAt_%I
BEFORE UPDATE ON %I
FOR EACH ROW EXECUTE PROCEDURE updated_at()',
t,t);
END loop;
END;
$$ language 'plpgsql';
此外,为了安全起见,您可以添加检查以查看触发器是否已存在于 information_schema.triggers
中。
IF NOT EXISTS ( SELECT 1 from information_schema.triggers
where trigger_name = 'update_updatedat_'|| t)
THEN
我希望通过自动更新 updated_at 列来自动执行每个 table 更新。我可以使用触发器为特定的 table 完成这项工作。但是我在任何地方都找不到的主要目标是创建一个函数,该函数动态获取模式中的所有 table,并创建相同的触发器,并且只更改 table 名称触发器正在引用。对于我的生活,我无法弄清楚。
我相信这不应该像我所做的那样棘手,因为我们的架构中的 table 将具有完全相同的列名称 'updated_at'。
我尝试过并认为可行的一个解决方案是将 table 模式转换为数组,并在每次迭代中迭代到 invoke/create 触发器。但是我没有大量的 psql 经验,所以我发现自己在谷歌上搜索了几个小时来解决这件小事。
SELECT ARRAY (
SELECT
table_name::text
FROM
information_schema.tables
WHERE table_schema = 'public') as tables;
我也试过:
DO $$
DECLARE
t text;
BEGIN
FOR t IN
SELECT table_name FROM information_schema.columns
WHERE column_name = 'updated_at'
LOOP
EXECUTE format('CREATE TRIGGER update_updatedAt
BEFORE UPDATE ON %I
FOR EACH ROW EXECUTE PROCEDURE updated_at()',
t);
END loop;
END;
$$ language 'plpgsql';
程序:
CREATE OR REPLACE FUNCTION updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
您的 DO
块有效。唯一的问题是我们不能为多个触发器使用相同的触发器名称。因此,您可以为触发器名称添加 table_name suffix/prefix。
DO $$
DECLARE
t text;
BEGIN
FOR t IN
SELECT table_name FROM information_schema.columns
WHERE column_name = 'updated_at'
LOOP
EXECUTE format('CREATE TRIGGER update_updatedAt_%I
BEFORE UPDATE ON %I
FOR EACH ROW EXECUTE PROCEDURE updated_at()',
t,t);
END loop;
END;
$$ language 'plpgsql';
此外,为了安全起见,您可以添加检查以查看触发器是否已存在于 information_schema.triggers
中。
IF NOT EXISTS ( SELECT 1 from information_schema.triggers
where trigger_name = 'update_updatedat_'|| t)
THEN