创建或替换触发器postgres

时间:2016-03-10 21:11:25

标签: sql postgresql triggers

我想“创建或替换”postgres表的触发器。但是,没有这样的sql表达式。

我看到我可以先做“DROP TRIGGER IF EXISTS”(http://www.postgresql.org/docs/9.5/static/sql-droptrigger.html)。

我的问题是:

  1. 是否有推荐/更好的选项(DROP + CREATE触发器)
  2. 是否存在没有“创建或替换触发器”的原因(这可能意味着我不应该这样做)
  3. 请注意,oracle(https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm)中有“创建或替换触发器”。然后,

    1. 这个命令是否计划用于Postgres?

6 个答案:

答案 0 :(得分:45)

无法创建或替换触发器,但可以这样做

DROP TRIGGER IF EXISTS yourtrigger_name on "yourschemaname"."yourtablename";

答案 1 :(得分:16)

Postres有事务DDL,所以BEGIN > DROP > CREATE > COMMIT is the equivalent of创建或替换`

https://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis是关于postgre的事务性DDL与其他系统(如oracle)比较的一个很好的写法

关于触发器的当前postgres计划功能(https://wiki.postgresql.org/wiki/Todo#Triggers)不包括添加REPLACE语法

答案 2 :(得分:5)

您应该使用两个语句:一个用于放置触发器,另一个用于创建触发器。

示例:

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();

答案 3 :(得分:3)

您可以在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;
$$

答案 4 :(得分:1)

您可以使用以下代码。

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 $$;

答案 5 :(得分:0)

这是一个 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)