首页 > 解决方案 > 使用 liquibase 修改 SQL-Server 中的数据类型和数据

问题描述

temp在使用 liquibase 创建的 SQL 服务器中有一个表

表的 liquibase 更改日志temp

databaseChangeLog:
  - changeSet:
      author: Author_name
      id: create_temp_table
      createTable:
        tableName: temp
        columns:
          - column:
              name: id
              type: BIGINT
              constraints:
                primaryKey: 'true'
          - column:
              name: type
              type: VARCHAR(255)
          - column:
              name: reference
              type: VARCHAR(255)
          - column:
              name: rate
              type: VARCHAR(255)

我想将rate列从字符串修改为十进制。所以我在下面创建了一个新的变更日志文件

databaseChangeLog:
  - changeSet:
      id: modify_column_temp_table
      author: Author_name
      changes:
        - modifyDataType:
            columnName: rate
            newDataType: DECIMAL(18,4)
            tableName: temp

temp现在,表中已经有一些以rate列为字符串的现有数据。当modify_column_temp_table更新日志运行时,我知道 SQl Server 会抛出一个转换错误,说字符串不能转换为十进制。

如何在同一更改日志中执行脚本或命令,该脚本或命令实际上会修改列的数据以及数据类型,以便将现有数据rate修改为新的数据类型?

标签: sqlsql-serverspring-bootliquibase

解决方案


这是一种常见的情况,它有一个众所周知的决定。您应该创建几个逐步修改数据库的变更集。

  1. 用新名称重命名原始列:
    <changeSet id="rename column" author="authorName" failOnError="true">
        <preConditions>
            <columnExists tableName="temp" columnName="rate"/>
            <!-- if you also wanna check the column type use <sqlCheck> with database-dependent syntax -->
        </preConditions>
        <renameColumn oldColumnName="rate" newColumnName="rate_number" tableName="temp"/>
    </changeSet>
  1. 使用新数据类型创建列:
    <changeSet id="create new column" author="authorName" failOnError="true">
        <preConditions>
            <columnExists tableName="temp" columnName="rate_number"/>
            <not>
                <columnExists tableName="temp" columnName="rate"/>
            </not>
        </preConditions>
        <addColumn tableName="temp">
            <column name="rate" type="NUMBER(38,0)"/>
        </addColumn>
    </changeSet>
  1. 使用特定于数据库的功能移动和转换数据:
    <changeSet id="copy data" author="authorName" failOnError="true">
        <preConditions>
            <columnExists tableName="rate" columnName="rate"/>
            <columnExists tableName="rate" columnName="rate_number"/>
        </preConditions>
        <sql>
            <!-- your database-specific sql code for copy and transform data -->
        </sql>
    </changeSet>

如您所愿,如果您想在工作流程中使用回滚功能,可以添加 <rollback> 语句。此外,您可以添加第四个更改集以删除名称为“rate_number”的列,但在删除此列之前测试应用程序可能很有用。

此处的任何 DDL 语句都需要不同的变更集,因为执行 DDL 语句会提交当前事务并且不能回滚。所以你应该手动处理更新过程中 liquibase 掉线的情况。


推荐阅读