Avo*_*nes 5 postgresql dynamic-sql plpgsql database-trigger
我对公共模式中所有表的触发器有以下查询:
SELECT 'CREATE TRIGGER ' || tab_name|| '_if_modified_trg INSERT OR UPDATE OR DELETE ON ' || tab_name|| ' FOR EACH ROW EXECUTE PROCEDURE audit.if_modified_func(); ' AS trigger_creation_query
FROM (
SELECT quote_ident(table_schema) || '.' || quote_ident(table_name) as tab_name
FROM information_schema.tables
WHERE table_schema='public'
) AS foo;
Run Code Online (Sandbox Code Playgroud)
我知道如何检查触发器是否存在:
SELECT tgname
from pg_trigger
where not tgisinternal AND tgname='randomname'
Run Code Online (Sandbox Code Playgroud)
但是,如何在第一个查询中检查同名触发器是否已存在 - 并跳过创建它并继续?这是我的解决方案,但它不起作用:
SELECT 'CREATE TRIGGER ' || tab_name|| '_if_modified_trg INSERT OR UPDATE OR DELETE ON ' || tab_name|| ' FOR EACH ROW EXECUTE PROCEDURE audit.if_modified_func(); ' AS trigger_creation_query
FROM (
SELECT quote_ident(table_schema) || '.' || quote_ident(table_name) as tab_name
FROM information_schema.tables
WHERE table_schema='public'
) AS foo
WHERE tab_name||'if_modified_trg' NOT IN (
SELECT tgname
from pg_trigger
where not tgisinternal );
Run Code Online (Sandbox Code Playgroud)
小智 5
使用它,您可以检查触发器是否存在,如果不存在则创建它。不要忘记最后一个“;”。
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'randomname') THEN
CREATE TRIGGER randomname
AFTER INSERT OR UPDATE OR DELETE ON randomtable
FOR EACH ROW EXECUTE PROCEDURE randomfunction();
END IF;
END
$$;
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助你。
您可以使用DO语句或 plpgsql 函数有条件地执行触发器创建:
DO
$do$
BEGIN
IF EXISTS (
SELECT 1
FROM pg_trigger
WHERE NOT tgisinternal AND tgname = 'randomname'
) THEN
-- do nothing
ELSE
-- create trigger
END IF;
END
$do$
Run Code Online (Sandbox Code Playgroud)
仔细检查后,您的其余代码也存在各种问题。看起来你正在尝试这样做:
DO
$do$
DECLARE
_tbl regclass;
_trg text;
BEGIN
FOR _tbl, _trg IN
SELECT c.oid::regclass, relname || '_if_modified_trg'
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'public'
AND c.relkind = 'r' -- only regular tables
LOOP
IF EXISTS (
SELECT
FROM pg_trigger
WHERE tgname = _trg
AND tgrelid = _tbl -- check only for respective table
) THEN
-- do nothing
ELSE
-- create trigger
EXECUTE format(
'CREATE TRIGGER %I
BEFORE INSERT OR UPDATE OR DELETE ON %s
FOR EACH ROW EXECUTE PROCEDURE audit.if_modified_func()'
, _trg, _tbl::text
);
END IF;
END LOOP;
END
$do$;
Run Code Online (Sandbox Code Playgroud)
我使用系统目录pg_class而不是出于information_schema.tables多种原因。最重要的是,它包含了oid表的 ,这使得检查pg_trigger更简单并且不易出错。
实际上,我们可以进一步简化并检查同一查询中是否存在触发器。速度快得多,但是:
DO
$do$
DECLARE
_tbl text;
_trg text;
BEGIN
FOR _tbl, _trg IN
SELECT c.oid::regclass::text, relname || '_if_modified_trg'
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_trigger t ON t.tgname = c.relname || '_if_modified_trg'
AND t.tgrelid = c.oid -- check only respective table
WHERE n.nspname = 'public'
AND c.relkind = 'r' -- only regular tables
AND t.tgrelid IS NULL -- trigger does not exist yet
LOOP
EXECUTE format(
'CREATE TRIGGER %I
BEFORE INSERT OR UPDATE OR DELETE ON %s
FOR EACH ROW EXECUTE PROCEDURE audit.if_modified_func()'
, _trg_name, _tbl_oid::text
);
END LOOP;
END
$do$;
Run Code Online (Sandbox Code Playgroud)
相关答案及更多解释:
| 归档时间: |
|
| 查看次数: |
7628 次 |
| 最近记录: |