我正在尝试使用 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
部分 中以转义所有包含的字符,否则这些字符将被识别为标记:
<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
代替。
压痕、修剪噪音。
您还可以使用保留字符:
< = <
> = >
代码:
<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>