如何使用Liquibase为PostgreSQL数据库创建触发器?

16

我正在使用dropwizard-migrations模块进行liquibase数据库重构。请参见此处的指南:http://dropwizard.codahale.com/manual/migrations/

当我运行 java -jar my_project.jar db migrate my_project.yml

我会得到以下错误:

ERROR [2013-09-11 20:53:43,089] liquibase: Change Set migrations.xml::11::me failed. Error: Error executing SQL CREATE OR REPLACE TRIGGER add_current_date_to_my_table BEFORE UPDATE ON my_table FOR EACH ROW EXECUTE PROCEDURE change_update_time();: ERROR: syntax error at or near "TRIGGER" Position: 19

这里是来自我的migrations.xml文件的一些相关变更集:

<changeSet id="1" author="me">
    <createProcedure>
        CREATE OR REPLACE FUNCTION change_update_time() RETURNS trigger
        LANGUAGE plpgsql
        AS $$
        BEGIN
        NEW.updated_at := CURRENT_TIMESTAMP;
        RETURN NEW;
        END;
        $$;
    </createProcedure>
    <rollback>
        DROP FUNCTION change_update_time();
    </rollback>
</changeSet>        

<changeSet id="2" author="me">
    <preConditions>
        <not>
            <tableExists tableName="my_table"/>
        </not>
    </preConditions>

    <createTable tableName="my_table">
        <column name="_id" type="integer" defaultValue="0">
            <constraints nullable="false"/>
        </column>
        <column name="updated_at" type="timestamp without time zone" defaultValue="now()">
            <constraints nullable="false"/>
        </column>
    </createTable>
</changeSet>

<changeSet id="3" author="me">
    <sql splitStatements="false">
        CREATE OR REPLACE TRIGGER add_current_date_to_my_table BEFORE UPDATE ON my_table FOR EACH ROW EXECUTE PROCEDURE change_update_time();
    </sql>
    <rollback>
        DROP TRIGGER add_current_date_to_my_table ON my_table;
    </rollback>
</changeSet>

我是否能创建触发器 add_current_date_to_my_table?这与创建函数时的“RETURNS trigger”功能重复吗?


1
我完全不了解Postgres,但存储过程能够自己工作吗?你得到的错误信息来自于Postgres。 "create or replace trigger" 能够正常工作吗?快速的谷歌搜索显示触发器可能会被删除,例如 DROP TRIGGER IF EXISTS...。无论如何,首先尝试手动创建触发器,确保它能正常工作。Liquibase只会执行相同的SQL语句。 - Jens
2个回答

22

解决方案是:

<changeSet id="3" author="me">
    <sql>
        DROP TRIGGER IF EXISTS add_current_date_to_my_table ON my_table;
        CREATE TRIGGER add_current_date_to_my_table BEFORE UPDATE ON my_table FOR EACH ROW EXECUTE PROCEDURE change_update_time();
    </sql>
    <rollback>
        DROP TRIGGER add_current_date_to_my_table ON my_table;
    </rollback>
</changeSet>

感谢Jens提供的提示。


0

Ann Kilzer提供了正确的答案,因为Postgres中没有CREATE OR REPLACE语句,不像PL/SQL。

所以我们需要将这个语句分成两个原子操作:

  1. DROP TRIGGER
  2. CREATE TRIGGER

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接