使用liquibase在mysql中创建触发器

使用liquibase在mysql中创建触发器,mysql,liquibase,Mysql,Liquibase,我想使用liquibase在mysql中创建一个简单的触发器。以下脚本直接从mysql工作: delimiter $$ CREATE TRIGGER myTrigger BEFORE INSERT ON myTable FOR EACH ROW BEGIN IF(NEW.my_timestamp IS NULL) THEN SET NEW.my_timestamp = now(); END IF; END$$ delimiter ; 因此,我想为li

我想使用liquibase在mysql中创建一个简单的触发器。以下脚本直接从mysql工作:

delimiter $$

CREATE TRIGGER myTrigger
    BEFORE INSERT ON myTable FOR EACH ROW
BEGIN
    IF(NEW.my_timestamp IS NULL) THEN
        SET NEW.my_timestamp = now();
    END IF;
END$$

delimiter ;
因此,我想为liquibase创建一个可以使用update命令应用此触发器的变更集,并在使用updateSQL命令时创建一个合适的sql脚本

我在变更集中尝试了各种选项,包括splitStatements和endDelimiter,但只能获得与update命令或updateSQL命令一起使用的选项。两者都不行

下面是一个使用格式化sql的示例更改集,当我使用update命令时,它可以正常工作,但当我使用updateSQL命令时,它不会创建合适的sql

-- liquibase formatted sql
-- changeset pcoates33:trigger-1 splitStatements:false

CREATE TRIGGER myTrigger
    BEFORE INSERT ON myTable FOR EACH ROW
BEGIN
    IF(NEW.my_timestamp IS NULL) THEN
        SET NEW.my_timestamp = now();
    END IF;
END

-- rollback DROP TRIGGER IF EXISTS myTrigger;
下面是一个我想要的updateSQL的工作方式,但更新失败:

-- liquibase formatted sql
-- changeset pcoates33:trigger-1 splitStatements:false

delimiter $$

CREATE TRIGGER myTrigger
    BEFORE INSERT ON myTable FOR EACH ROW
BEGIN
    IF(NEW.my_timestamp IS NULL) THEN
        SET NEW.my_timestamp = now();
    END IF;
END$$

delimiter ;

-- rollback DROP TRIGGER IF EXISTS myTrigger;
基本问题是

  • mysql脚本需要分隔符$$和分隔符;在里面
  • 如果liquibase在开始处有分隔符$$,那么它发出的jdbc调用将失败

  • 您的触发器可以轻松转换为单语句形式:

    创建触发器myTrigger
    插入前
    在我的桌子上
    每行
    设置NEW.my_timestamp=COALESCE(NEW.my_timestamp,NOW());
    
    不需要重新分配分隔符



    如果由于该列根本没有列在INSERT查询的列列表中而将NULL插入该列,则您可以在列定义中简单地使用
    DEFAULT CURRENT\u TIMESTAMP
    ,并且不需要触发器。但如果显式设置空值,则此方法不适用。

    您的触发器可能很容易转换为单语句形式:

    创建触发器myTrigger
    插入前
    在我的桌子上
    每行
    设置NEW.my_timestamp=COALESCE(NEW.my_timestamp,NOW());
    
    不需要重新分配分隔符



    如果由于该列根本没有列在INSERT查询的列列表中而将NULL插入该列,则您可以在列定义中简单地使用
    DEFAULT CURRENT\u TIMESTAMP
    ,并且不需要触发器。但如果显式设置空值,则此方法不适用。

    我同意@Akina的观点,一个好的解决方案是不使用触发器,或者将它们压缩为单个语句

    我正在尝试将liquibase引入现有数据库,因此希望最初能够保持不变。然后应用更改使其更简单

    所以,基本问题是

  • mysql脚本需要分隔符$$和分隔符;在里面
  • 如果liquibase在开始处有分隔符$$,那么它发出的jdbc调用将失败
  • 经过多次尝试,我找到的解决方案依赖于使用gradle插件来运行liquibase updateSql命令。我一个人用液化糖吃不下去。我基本上会对liquibase无法识别的代码部分进行注释,然后对liquibase创建的脚本文件进行后期处理,以取消对语句的注释

    以下是我的更改集,格式为sql:

    -- liquibase formatted sql
    -- changeset pcoates33:trigger-1 splitStatements:false stripComments:false
    -- delimiter $$
    
    CREATE TRIGGER myTrigger
        BEFORE INSERT ON myTable FOR EACH ROW
    BEGIN
        IF(NEW.my_timestamp IS NULL) THEN
            SET NEW.my_timestamp = now();
        END IF;
    END-- $$
    
    -- delimiter ;
    -- rollback DROP TRIGGER IF EXISTS myTrigger;
    
    我可以用它运行liquibase更新,并且它被正确应用

    我将gradle配置为使用liquibase插件,并使用输出文件:“$projectDir/update.sql”

    然后更新build.gradle文件以扩展updateSql任务,该任务由插件添加,用于更改输出中所需语句的注释

    updateSQL{
      doLast {
        ant.replace(file: "$projectDir/update.sql", token: '-- delimiter', value: 'delimiter')
        ant.replace(file: "$projectDir/update.sql", token: '-- $$', value: '$$')
      }
    }
    

    我同意@Akina的观点,一个好的解决方案是要么不使用触发器,要么将它们压缩成单个语句

    我正在尝试将liquibase引入现有数据库,因此希望最初能够保持不变。然后应用更改使其更简单

    所以,基本问题是

  • mysql脚本需要分隔符$$和分隔符;在里面
  • 如果liquibase在开始处有分隔符$$,那么它发出的jdbc调用将失败
  • 经过多次尝试,我找到的解决方案依赖于使用gradle插件来运行liquibase updateSql命令。我一个人用液化糖吃不下去。我基本上会对liquibase无法识别的代码部分进行注释,然后对liquibase创建的脚本文件进行后期处理,以取消对语句的注释

    以下是我的更改集,格式为sql:

    -- liquibase formatted sql
    -- changeset pcoates33:trigger-1 splitStatements:false stripComments:false
    -- delimiter $$
    
    CREATE TRIGGER myTrigger
        BEFORE INSERT ON myTable FOR EACH ROW
    BEGIN
        IF(NEW.my_timestamp IS NULL) THEN
            SET NEW.my_timestamp = now();
        END IF;
    END-- $$
    
    -- delimiter ;
    -- rollback DROP TRIGGER IF EXISTS myTrigger;
    
    我可以用它运行liquibase更新,并且它被正确应用

    我将gradle配置为使用liquibase插件,并使用输出文件:“$projectDir/update.sql”

    然后更新build.gradle文件以扩展updateSql任务,该任务由插件添加,用于更改输出中所需语句的注释

    updateSQL{
      doLast {
        ant.replace(file: "$projectDir/update.sql", token: '-- delimiter', value: 'delimiter')
        ant.replace(file: "$projectDir/update.sql", token: '-- $$', value: '$$')
      }
    }
    

    分隔符
    命令是CLI的命令。liquibase可能不支持它…@Akina我知道-我正在试图找到一种方法,让liquibase在运行更新(即jdbc调用)时忽略分隔符语句,但在运行updateSQL时包含它。据我所知,使用liquibase是不可能的。看看-也许会有帮助。
    DELIMITER
    命令是CLI的一个命令。liquibase可能不支持它…@Akina我知道-我正在试图找到一种方法,让liquibase在运行更新(即jdbc调用)时忽略分隔符语句,但在运行updateSQL时包含它。据我所知,这是不可能与液化。看看-也许会有帮助。谢谢你-我认为我的例子有点太简单了。这确实是一个更一般的问题,我希望能够在触发器中使用多个语句。我同意触发器不是设置时间戳的好主意。谢谢你,我觉得我的例子有点太简单了。这确实是一个更一般的问题,我希望能够在触发器中使用多个语句。我同意触发器不是设置时间戳的好主意。