我正在使用Liquibase生成MySQL和HSQLDB数据库。
在几个表中,我有一个名为'last_modified'的列,它是该特定记录上次更新的TIMESTAMP。
<changeSet author="bob" id="7">
<createTable tableName="myTable">
<column autoIncrement="true" name="id" type="INT">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="name" type="VARCHAR(128)">
<constraints nullable="false" />
</column>
<column name="description" type="VARCHAR(512)" />
<column defaultValueBoolean="true" name="enabled" type="BIT">
<constraints nullable="false" />
</column>
<column name="last_modified" type="TIMESTAMP"/>
</createTable>
<modifySql dbms="mysql">
<append value=" engine innodb" />
</modifySql>
</changeSet>
我注意到如果我使用MySQL,那么为该列生成的SQL是:
`last_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
虽然如果我使用HSQLDB,在更新的情况下没有任何反应,但我希望MySQL数据库具有相同的行为,更新时的默认值等于CURRENT_TIMESTAMP。
如何将CURRENT_TIMESTAMP设置为ON UPDATE的默认值?
答案 0 :(得分:6)
您无法使用默认值执行此操作。 MySQL行为是非标准的,其他数据库不支持。正确的方法是使用TRIGGER定义为BEFORE UPDATE,并在每次更新行时设置时间戳。
更新:从HSQLDB版本2.3.4开始支持此功能。例如:CREATE TABLE T1(ID INT, last_modified timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL)
。请注意,NOT NULL约束必须出现在DEFAULT和ON UPDATE子句之后。
答案 1 :(得分:5)
或者您可以尝试这样做,因为您已经添加了modifySql
标记:
<column defaultValue="CURRENT_TIMESTAMP"
name="timestamp"
type="TIMESTAMP">
<constraints nullable="false"/>
</column>
<modifySql dbms="mysql">
<regExpReplace replace="'CURRENT_TIMESTAMP'" with="CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"/>
<append value=" engine innodb" />
</modifySql>
Liquibase 3.1.1不会产生您上面描述的内容。我必须如上所述处理它
答案 2 :(得分:4)
我们实际上使用Liquibase用于完全相同的用例。您将要像fredt描述的那样创建更新触发器。否则,您无法确定除MySQL之外的其他数据库是否会发生更新。您的变更集标记将记录如下内容:
<sql splitStatements="false">
CREATE TRIGGER update_${tableName}_trg
BEFORE UPDATE ON ${tableName}
FOR EACH ROW BEGIN
SET NEW.updated_at = NOW();
END
</sql>
另外,我在Stack Overflow上有一个关于如何重构您可以在How do you refactor similar looking code and provide params in Liquibase?看到的部分代码的问题。