在 Liquibase 中创建函数时出现“旧 <> 新”错误

问题描述 投票:0回答:2

我正在尝试使用 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>
标签将其简单地写为语句,但仍然出现相同的错误。

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

postgresql plpgsql liquibase
2个回答
2
投票

由于 Liquibase 使用 XML 格式,请将整个

CREATE FUNCTION
语句包装在
CDATA
部分
中以转义所有包含的字符,否则这些字符将被识别为标记:

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

除了

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

参见:

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

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

  • 如果任何行包含
  • NEW <> OLD

    字段,

    NULL
    将失败。如果定义了所有涉及的列
    NOT NULL
    那就可以了。否则请使用
    NEW IS DISTINCT FROM OLD
    代替。

  • 压痕、修剪噪音。


0
投票

您还可以使用保留字符

< = &lt;
> = &gt;

代码:

<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 &lt;&gt; 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>
© www.soinside.com 2019 - 2024. All rights reserved.