【问题标题】:Create or replace trigger postgres创建或替换触发器 postgres
【发布时间】:2016-06-25 22:32:49
【问题描述】:

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

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

我的问题是:

  1. 是否有比(DROP + CREATE 触发器)推荐/更好的选项
  2. 没有这样的“创建或替换触发器”是否有原因(这可能暗示我不应该这样做)

请注意,oracle (https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm) 中有一个“Create or Replace Trigger”。那么,

  1. 是否为 Postgres 计划过这样的命令?

【问题讨论】:

标签: sql postgresql ddl database-trigger


【解决方案1】:

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

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

【讨论】:

  • 轰隆隆。你真的救了我的命
【解决方案2】:

Postgresql 有事务 DDL,所以 BEGIN > DROP > CREATE > COMMIT 相当于 CREATE OR REPLACE

This 很好地描述了 postgre 的事务 DDL 与其他系统(例如 oracle)的比较

关于 triggers 的当前 postgres 计划功能不包括添加 REPLACE 语法。

【讨论】:

  • 为什么 postgreql 允许 CREATE OR REPLACE FUNCTION 而不允许 CREATE OR REPLACE TRIGGER... 如果它要遵循一个概念,它应该对函数强制执行它对吗?还是我错了?
  • 现在向我提出百万美元的问题,寻求真相!
  • 我认为其他对象可能依赖于触发器,如果​​您删除触发器,它也会删除其他对象(在级联的情况下)。
  • 这不是真的。由于ERROR: cannot drop view currency_rate because other objects depend on it DETAIL: composite type consume_info column currency_rate depends on type currency_rate,我无法删除视图
  • @CrystalPaladin 您不能删除正在被另一个函数使用的函数。 DROPCREATE 技术不适用于函数,这就是 CREATE OR REPLACE 存在的原因。
【解决方案3】:

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

例子:

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

【讨论】:

  • BEGIN;COMMIT; 拍在那里,你应该会很好。
【解决方案4】:

你可以使用下面的代码。

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】:

    您可以将CREATE OR REPLACE FUNCTION trigger_function 与您的 SQL 中的以下脚本结合使用:

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

    【讨论】:

      【解决方案6】:

      从 PostgreSQL 14 开始,CREATE TRIGGER now also supports "OR REPLACE"

      您现在可以使用CREATE OR REPLACE TRIGGER ...(而不是先使用DROP TRIGGER IF EXISTS)。

      这似乎也可以明智地处理分区表的情况:

      在分区表上创建行级触发器将导致在其每个现有分区上创建相同的“克隆”触发器;并且稍后创建或附加的任何分区也将具有相同的触发器。如果子分区上已经存在名称冲突的触发器,则会发生错误,除非使用 CREATE OR REPLACE TRIGGER,在这种情况下,该触发器将替换为克隆触发器。当一个分区与其父分区分离时,它的克隆触发器将被删除。

      同样值得注意:

      目前,约束触发器不支持 OR REPLACE 选项。

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多