使用迁移工具时如何编写幂等迁移

问题描述

考虑下面的两个迁移脚本。脚本由执行脚本的迁移工具运行,并在成功时插入 [dbo].[MigrationHistory] 以跟踪迁移历史。

(1)检查表是否存在

-- File: 0050-CreatePersonsTable.sql

-- Only check if the table exists; create if not.

IF NOT EXISTS (
  SELECT TOP 1 *
  FROM informatION_SCHEMA.TABLES
  WHERE TABLE_SCHEMA = 'dbo'
  AND TABLE_NAME = 'Persons'
)
BEGIN
  CREATE TABLE [dbo].[Persons] (
    PersonID int,LastName varchar(255),FirstName varchar(255),Address varchar(255),City varchar(255)
  )
END

(2)查看迁移历史表

-- File: 0050-CreatePersonsTable.sql

-- Check migration history table to see if '0050-CreatePersonsTable.sql' 
-- was already applied

IF NOT EXISTS (
    SELECT * 
    FROM [dbo].[MigrationHistory] 
    WHERE ScriptName = '0050-CreatePersonsTable.sql'
)
BEGIN
  CREATE TABLE [dbo].[Persons] (
    PersonID int,City varchar(255)
  )
END

-- On success the migration tool inserts '0050-CreatePersonsTable.sql'
-- into the [dbo].[MigrationHistory] table.

问题:

我认为第一个迁移脚本是一种编写迁移的误导性方法

IF NOT EXISTS (...) 谓词具有误导性。如果之前执行的迁移已经创建了表怎么办?然后将跳过此迁移,数据库将处于意外状态。现在为了解决这个问题,我可以添加一个额外的检查来查看表是否存在,然后执行一组不同的指令。这没问题,但是如果表存在并且预期的列存在但数据类型错误(例如,姓氏是 nvarchar)怎么办。现在我可以写一个检查数据类型是否正确,如果不正确则修复它们。

这些谓词很快就会失控。

为什么不避免所有这些并只检查 [dbo].[MigrationHistory] 表?在这种情况下,迁移工具按顺序执行迁移。即 0001 到 0049 迁移在 0050-CreatePersonsTable.sql 之前运行。我期望在应用此迁移时数据库处于特定状态。如果 [dbo].[Persons] 表已经存在(无论出于何种原因),那么我希望迁移失败,因为数据库处于意外状态。

声明:第二次迁移是更好、更安全的迁移。

有什么我忽略的东西吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)