创建或替换触发器 postgres
Create or replace trigger postgres
我想 "create or replace" 一个 postgres table 的触发器。但是,没有这样的sql表达式。
我知道我可以先做一个“DROP TRIGGER IF EXISTS
”(http://www.postgresql.org/docs/9.5/static/sql-droptrigger.html)。
我的问题是:
- 是否有 recommended/better 选项而不是 (
DROP
+ CREATE
触发器)
- 有没有这样的原因"create or replace trigger"(这可能意味着我不应该想要这样做)
注意在oracle中有一个“Create or Replace Trigger
”(https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm)。然后,
- 是否为 Postgres 计划了这样的命令?
Postgresql 有事务 DDL,所以 BEGIN > DROP > CREATE > COMMIT
等同于 CREATE OR REPLACE
This 是一篇很好的文章,介绍了 postgre 的事务性 DDL 与其他系统(例如 oracle)的比较
当前 postgres 计划的有关 triggers 的功能不包括添加 REPLACE
语法。
无法创建或替换触发器,但可以这样做
DROP TRIGGER IF EXISTS yourtrigger_name on "yourschemaname"."yourtablename";
您应该使用两个语句:一个用于放置触发器,另一个用于创建触发器。
示例:
DROP TRIGGER IF EXISTS my_trigger
ON my_schema.my_table;
CREATE TRIGGER my_trigger
BEFORE INSERT OR UPDATE
ON my_schema.my_table
FOR EACH ROW EXECUTE PROCEDURE my_schema.my_function();
您可以使用下面的代码。
DO $$ BEGIN
CREATE (trigger, type , ...);
EXCEPTION
WHEN others THEN null;
END $$;
示例:
DO $$ BEGIN
CREATE TRIGGER trigger_workIDExist
BEFORE INSERT OR UPDATE ON "GalleryModel"
FOR EACH ROW EXECUTE PROCEDURE check_workIDExist();
EXCEPTION
WHEN others THEN null;
END $$;
您可以在 SQL 中将 CREATE OR REPLACE FUNCTION trigger_function
与以下脚本结合使用:
DO $$
BEGIN
IF NOT EXISTS(SELECT *
FROM information_schema.triggers
WHERE event_object_table = 'table_name'
AND trigger_name = 'trigger_name'
)
THEN
CREATE TRIGGER trigger_name AFTER INSERT ON table_name FOR EACH ROW EXECUTE PROCEDURE trigger_function();
END IF;
END;
$$
这是一个 Python 脚本,它从 postgresql 转储文件中提取所有触发器以进行重建。我使用许多与 QGIS 配合得很好的堆叠视图;这对维护依赖视图有很大帮助。
基于 Ali Bagheri 的出色回答。
import pathlib
import re
import sys
re_pat_str = r'^\s*CREATE TRIGGER.*?;\s*$'
sql_wrapper_str = """
DO $$ BEGIN
{trigger_str}
EXCEPTION WHEN others THEN null;
END $$;
"""
if __name__ == "__main__":
sql_file = pathlib.Path(sys.argv[1])
with sql_file.open("r", encoding="utf8") as f:
sql_str = f.read()
re_pat = re.compile(re_pat_str, re.MULTILINE | re.DOTALL)
parts = []
for i, m in enumerate(re_pat.finditer(sql_str)):
parts.append(sql_wrapper_str.format(trigger_str=m[0].strip()))
new_sql_str = "\n".join(parts)
new_sql_file = sql_file.parent / f'{sql_file.stem}.trigger{sql_file.suffix}'
with new_sql_file.open("w", encoding="utf8") as f:
f.write(new_sql_str)
从 PostgreSQL 14 开始,CREATE TRIGGER
now also supports "OR REPLACE
"。
您现在可以使用 CREATE OR REPLACE TRIGGER ...
(而不是先使用 DROP TRIGGER IF EXISTS
)。
这似乎也明智地处理了分区表的情况:
Creating a row-level trigger on a partitioned table will cause an identical “clone” trigger to be created on each of its existing partitions; and any partitions created or attached later will have an identical trigger, too. If there is a conflictingly-named trigger on a child partition already, an error occurs unless CREATE OR REPLACE TRIGGER is used, in which case that trigger is replaced with a clone trigger. When a partition is detached from its parent, its clone triggers are removed.
同样值得一提的是:
Currently, the OR REPLACE option is not supported for constraint triggers.
我想 "create or replace" 一个 postgres table 的触发器。但是,没有这样的sql表达式。
我知道我可以先做一个“DROP TRIGGER IF EXISTS
”(http://www.postgresql.org/docs/9.5/static/sql-droptrigger.html)。
我的问题是:
- 是否有 recommended/better 选项而不是 (
DROP
+CREATE
触发器) - 有没有这样的原因"create or replace trigger"(这可能意味着我不应该想要这样做)
注意在oracle中有一个“Create or Replace Trigger
”(https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm)。然后,
- 是否为 Postgres 计划了这样的命令?
Postgresql 有事务 DDL,所以 BEGIN > DROP > CREATE > COMMIT
等同于 CREATE OR REPLACE
This 是一篇很好的文章,介绍了 postgre 的事务性 DDL 与其他系统(例如 oracle)的比较
当前 postgres 计划的有关 triggers 的功能不包括添加 REPLACE
语法。
无法创建或替换触发器,但可以这样做
DROP TRIGGER IF EXISTS yourtrigger_name on "yourschemaname"."yourtablename";
您应该使用两个语句:一个用于放置触发器,另一个用于创建触发器。
示例:
DROP TRIGGER IF EXISTS my_trigger
ON my_schema.my_table;
CREATE TRIGGER my_trigger
BEFORE INSERT OR UPDATE
ON my_schema.my_table
FOR EACH ROW EXECUTE PROCEDURE my_schema.my_function();
您可以使用下面的代码。
DO $$ BEGIN
CREATE (trigger, type , ...);
EXCEPTION
WHEN others THEN null;
END $$;
示例:
DO $$ BEGIN
CREATE TRIGGER trigger_workIDExist
BEFORE INSERT OR UPDATE ON "GalleryModel"
FOR EACH ROW EXECUTE PROCEDURE check_workIDExist();
EXCEPTION
WHEN others THEN null;
END $$;
您可以在 SQL 中将 CREATE OR REPLACE FUNCTION trigger_function
与以下脚本结合使用:
DO $$
BEGIN
IF NOT EXISTS(SELECT *
FROM information_schema.triggers
WHERE event_object_table = 'table_name'
AND trigger_name = 'trigger_name'
)
THEN
CREATE TRIGGER trigger_name AFTER INSERT ON table_name FOR EACH ROW EXECUTE PROCEDURE trigger_function();
END IF;
END;
$$
这是一个 Python 脚本,它从 postgresql 转储文件中提取所有触发器以进行重建。我使用许多与 QGIS 配合得很好的堆叠视图;这对维护依赖视图有很大帮助。
基于 Ali Bagheri 的出色回答。
import pathlib
import re
import sys
re_pat_str = r'^\s*CREATE TRIGGER.*?;\s*$'
sql_wrapper_str = """
DO $$ BEGIN
{trigger_str}
EXCEPTION WHEN others THEN null;
END $$;
"""
if __name__ == "__main__":
sql_file = pathlib.Path(sys.argv[1])
with sql_file.open("r", encoding="utf8") as f:
sql_str = f.read()
re_pat = re.compile(re_pat_str, re.MULTILINE | re.DOTALL)
parts = []
for i, m in enumerate(re_pat.finditer(sql_str)):
parts.append(sql_wrapper_str.format(trigger_str=m[0].strip()))
new_sql_str = "\n".join(parts)
new_sql_file = sql_file.parent / f'{sql_file.stem}.trigger{sql_file.suffix}'
with new_sql_file.open("w", encoding="utf8") as f:
f.write(new_sql_str)
从 PostgreSQL 14 开始,CREATE TRIGGER
now also supports "OR REPLACE
"。
您现在可以使用 CREATE OR REPLACE TRIGGER ...
(而不是先使用 DROP TRIGGER IF EXISTS
)。
这似乎也明智地处理了分区表的情况:
Creating a row-level trigger on a partitioned table will cause an identical “clone” trigger to be created on each of its existing partitions; and any partitions created or attached later will have an identical trigger, too. If there is a conflictingly-named trigger on a child partition already, an error occurs unless CREATE OR REPLACE TRIGGER is used, in which case that trigger is replaced with a clone trigger. When a partition is detached from its parent, its clone triggers are removed.
同样值得一提的是:
Currently, the OR REPLACE option is not supported for constraint triggers.