Liquibase & MySQL 5.7 时间戳列修改问题
Liquibase & MySQL 5.7 timestamp column modification problem
我有一个名为 updated_time
的列,它分配了 timestamp
数据类型:
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
问题是目前这个列支持秒精度。我需要它能够存储毫秒精度。
因此,我准备了以下 Liquibase 变更集:
{
"databaseChangeLog": [
{
"changeSet": {
"id": "1",
"changes": [
{
"modifyDataType": {
"columnName": "updated_time",
"newDataType": "timestamp(3)",
"tableName": "mytable"
},
"addDefaultValue": {
"columnDataType": "timestamp(3)",
"columnName": "updated_time",
"defaultValueComputed": "current_timestamp(3)",
"tableName": "mytable"
},
"addNotNullConstraint": {
"columnDataType": "timestamp(3)",
"columnName": "updated_time",
"tableName": "mytable"
}
}
]
}
}
]
}
不幸的是,这个变更集总是失败。
原因如下:
2019-11-08 00:57:28.624 WARN [] 99326 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migration failed for change set ...
Reason: liquibase.exception.DatabaseException: Invalid default value for 'updated_time' [Failed SQL: (1067) ALTER TABLE maas.mytable MODIFY updated_time timestamp(3)]
我看到一些帖子说 5.7 版中 timestamp
数据类型发生了一些变化。也就是说,默认情况下,我无法为 timestamp
列分配非零(空)值。而且,为了修复它,我必须对服务器配置本身进行一些更改。
假设我对服务器的访问权限有限,我不能简单地去修改配置,在 Liquibase 中是否有解决此问题的优雅方法?
如果你想将timestamp
转换成bigint
,那么你可以通过以下方式进行:
- 创建一个新列,例如
bigint_date
;
- 使用当前
timestamp_date
列中的 bigint 值填充它;
- 删除您的
timestamp_date
列;
Liquibase 变更集可能如下所示:
<changeSet id="foo1" author="bar">
<preConditions onFail="MARK_RAN">
<not>
<columnExists tableName="your_table" columnName="bigint_date"/>
</not>
</preConditions>
<comment>Add new column</comment>
<addColumn tableName="your_table">
<column name="bigint_date" type="bigint(13)"/>
</addColumn>
</changeSet>
<changeSet id="foo2" author="bar">
<preConditions onFail="MARK_RAN">
<columnExists tableName="your_table" columnName="bigint_date"/>
<columnExists tableName="your_table" columnName="timestamp_date"/>
</preConditions>
<comment>Populate it with bigint values from your current "timestamp_date" column</comment>
<update tableName="your_table">
<column name="bigint_date" valueComputed="SELECT UNIX_TIMESTAMP(timestamp_date) FROM your_table"/>
</update>
</changeSet>
<changeSet id="foo3" author="bar">
<preConditions onFail="MARK_RAN">
<columnExists tableName="your_table" columnName="timestamp_date"/>
</preConditions>
<comment>Drop your "timestamp_date" column</comment>
<dropColumn tableName="your_table" columnName="timestamp_date"/>
</changeSet>
<changeSet id="foo4" author="bar">
<preConditions onFail="MARK_RAN">
<columnExists tableName="your_table" columnName="bigint_date"/>
</preConditions>
<comment>Update NULL values</comment>
<update tableName="your_table">
<column name="bigint_date" valueComputed="UNIX_TIMESTAMP()"/>
<where>bigint_date IS NULL</where>
</update>
</changeSet>
我有一个名为 updated_time
的列,它分配了 timestamp
数据类型:
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
问题是目前这个列支持秒精度。我需要它能够存储毫秒精度。
因此,我准备了以下 Liquibase 变更集:
{
"databaseChangeLog": [
{
"changeSet": {
"id": "1",
"changes": [
{
"modifyDataType": {
"columnName": "updated_time",
"newDataType": "timestamp(3)",
"tableName": "mytable"
},
"addDefaultValue": {
"columnDataType": "timestamp(3)",
"columnName": "updated_time",
"defaultValueComputed": "current_timestamp(3)",
"tableName": "mytable"
},
"addNotNullConstraint": {
"columnDataType": "timestamp(3)",
"columnName": "updated_time",
"tableName": "mytable"
}
}
]
}
}
]
}
不幸的是,这个变更集总是失败。
原因如下:
2019-11-08 00:57:28.624 WARN [] 99326 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migration failed for change set ...
Reason: liquibase.exception.DatabaseException: Invalid default value for 'updated_time' [Failed SQL: (1067) ALTER TABLE maas.mytable MODIFY updated_time timestamp(3)]
我看到一些帖子说 5.7 版中 timestamp
数据类型发生了一些变化。也就是说,默认情况下,我无法为 timestamp
列分配非零(空)值。而且,为了修复它,我必须对服务器配置本身进行一些更改。
假设我对服务器的访问权限有限,我不能简单地去修改配置,在 Liquibase 中是否有解决此问题的优雅方法?
如果你想将timestamp
转换成bigint
,那么你可以通过以下方式进行:
- 创建一个新列,例如
bigint_date
; - 使用当前
timestamp_date
列中的 bigint 值填充它; - 删除您的
timestamp_date
列;
Liquibase 变更集可能如下所示:
<changeSet id="foo1" author="bar">
<preConditions onFail="MARK_RAN">
<not>
<columnExists tableName="your_table" columnName="bigint_date"/>
</not>
</preConditions>
<comment>Add new column</comment>
<addColumn tableName="your_table">
<column name="bigint_date" type="bigint(13)"/>
</addColumn>
</changeSet>
<changeSet id="foo2" author="bar">
<preConditions onFail="MARK_RAN">
<columnExists tableName="your_table" columnName="bigint_date"/>
<columnExists tableName="your_table" columnName="timestamp_date"/>
</preConditions>
<comment>Populate it with bigint values from your current "timestamp_date" column</comment>
<update tableName="your_table">
<column name="bigint_date" valueComputed="SELECT UNIX_TIMESTAMP(timestamp_date) FROM your_table"/>
</update>
</changeSet>
<changeSet id="foo3" author="bar">
<preConditions onFail="MARK_RAN">
<columnExists tableName="your_table" columnName="timestamp_date"/>
</preConditions>
<comment>Drop your "timestamp_date" column</comment>
<dropColumn tableName="your_table" columnName="timestamp_date"/>
</changeSet>
<changeSet id="foo4" author="bar">
<preConditions onFail="MARK_RAN">
<columnExists tableName="your_table" columnName="bigint_date"/>
</preConditions>
<comment>Update NULL values</comment>
<update tableName="your_table">
<column name="bigint_date" valueComputed="UNIX_TIMESTAMP()"/>
<where>bigint_date IS NULL</where>
</update>
</changeSet>