在 Liquibase 中创建函数时 "OLD <> NEW" 处出错

Error at "OLD <> NEW" when creating function in Liquibase

我正在尝试使用 Liqubase 创建触发器函数。以下是我的更改集:

<changeSet id="1" author="valen" dbms ="postgresql" >
    <createProcedure>
        CREATE OR REPLACE FUNCTION public.onupdate_update_mod_ver()
        RETURNS trigger
        LANGUAGE plpgsql
        AS $function$
        BEGIN
        IF NEW <> OLD THEN
        UPDATE mod_ver SET rec_change_date = current_timestamp where id = new.id;
        END IF;
        RETURN NEW;
        END;
        $function$;
    </createProcedure>
    <rollback>
        DROP FUNCTION onupdate_update_mod_ver();
    </rollback>
</changeSet>

它在 IF NEW <> OLD THEN 行抛出语法错误。
它说 tag name expected。基本上它读取 <> 作为标签而不是“不等于”。

我尝试使用 != 但没有成功。

注意:直接在数据库中执行该函数是正确的,但是如果有更改日志就不行了。我也尝试使用 <sql> 标签将其简单地写成语句但仍然是同样的错误。

知道如何绕过这个问题吗?

由于 Liquibase 使用 XML 格式,将整个 CREATE FUNCTION 语句包装在 CDATA section 中以转义所有包含的字符,否则识别为标记:

<changeSet id="1" author="valen" dbms ="postgresql">
    <createProcedure>
       <![CDATA[ 
        CREATE OR REPLACE FUNCTION public.onupdate_update_mod_ver()
          RETURNS trigger
          LANGUAGE plpgsql AS
        $func$
        BEGIN
           IF NEW IS DISTINCT FROM OLD THEN
              UPDATE public.mod_ver
              SET    rec_change_date = CURRENT_TIMESTAMP
              WHERE  id = NEW.id;
           END IF;
           RETURN NEW;
        END
        $func$
       ]]> 
    </createProcedure>
    <rollback>
        DROP FUNCTION public.onupdate_update_mod_ver()
    </rollback>
</changeSet>

除了<之外,$(用于美元引用函数体)也有特殊含义。

参见:

  • What does <![CDATA[]]> in XML mean?

同时我添加了一些其他建议:

  • 如果在创建时对函数进行模式限定是有意义的,那么在删除时进行同样的操作也是有意义的。 (并以相同的方式对更新后的 table 进行架构限定。)

  • 如果任何行包含 NULL 字段,
  • NEW <> OLD 将失败。如果所有涉及的列都已定义 NOT NULL 没关系。否则使用 NEW IS DISTINCT FROM OLD 代替。

  • 缩进,trim噪音。