4

新列已添加到表中,但新列并未添加到表定义的末尾(最右边的列),而是添加到表的中间。

表差异

当我尝试在 Redgate SQL 源代码控制中提交此操作时,我收到警告“这些更改可能导致数据丢失”

  • 数据丢失真的会发生吗?
  • 有没有办法预览更改脚本以确认不会丢失任何数据?
    • 我可以复制脚本并轻松将其转换为 Migrations V2 脚本吗?
  • 我只需要
    • 在 SSMS 中编辑表格并将新列移动到末尾
    • 或编写迁移脚本?
  • 如果是这样,是否有任何方便的工具来做重复的事情?
4

3 回答 3

5

预先披露我为 Red Gate 工作的 SQL 源代码控制。

该更改将需要重新创建一个表。默认情况下,SSMS 不会让您保存该更改。但是,必须在 SSMS 中禁用该选项。它位于工具->选项->设计器->表和数据库设计器->防止保存需要重新创建表的更改。

鉴于该功能被禁用,SQL 源代码控制随后将其视为潜在的数据丢失情况,并提示您查看是否要添加迁移脚本。

如果您团队中的其他开发人员通过获取最新信息来获取此更改,则 SQL 源代码控制将让他们了解任何潜在的数据丢失,并提供更多详细信息,具体取决于他们本地数据库的当前状态。如果唯一的更改是将列添加到现有表,那么这不会删除未更改的列中的数据。

如果您正在部署到另一个数据库(例如 staging/UAT/prod)并且您有 SQL 比较,那么您可以使用它来查看如果您尝试针对另一个非本地数据库运行它,那么将准确地查看将应用于数据库的内容。选择创建部署脚本选项,您可以在运行前检查 SQL。

正如您所说,将列添加到表的末尾将避免重建的需要,因此如果您不需要担心列的位置,那么这可能是避免这种情况的最简单方法。

或者,您可以将迁移脚本添加到:

  1. 使用临时名称创建具有新结构的新表
  2. 将现有数据复制到临时表
  3. 删除现有表
  4. 将新的临时表重命名为原始名称

您提到了 Migrations v2,这是一个测试版功能,它改变了迁移的工作方式,以便更好地支持分支和合并以及 DVCS 系统。见http://www.red-gate.com/migrations

版本 1 迁移脚本需要进行一些修改才能转换为 v2 迁移脚本。这是一个相当微不足道的变化。我们目前正在努力记录这一点,如果您想了解有关此更改的更多信息,请通过 Google 群组与我们联系。https://groups.google.com/forum/#!forum/red-gate-migrations

于 2013-10-14T10:35:07.750 回答
1

我使用 SSMS 将该列移动到表的末尾,以消除对迁移脚本的需要。

在类似的情况下,移动列不方便,这就是我将 SSMS 脚本转换为 Migrations V2 脚本的方法。

  • 撤消 SSMS 中的更改(已删除该列)
  • 重做 SSMS 中的更改,但我没有将更改直接保存到数据库,而是保存了更改脚本
  • 修改了更改脚本
    • 修剪 SSMS 事务和环境包装器
    • 添加了一个保护子句:IF COL_LENGTH('MyTable','MyColumn') IS NULL
    • 将脚本包装在 BEGIN TRAN - ROLLBACK TRAN 中以测试脚本而不弄脏数据库
    • 将 GO 替换为 END BEGIN
    • 在回滚事务中测试
    • 删除了 BEGIN TRAN - ROLLBACK TRAN 开发包装

将 SSMS 转换为 Redgate 的视觉差异

于 2013-10-16T09:40:06.460 回答
0

这是一个简单的 sql 查询,有助于在数据库表中插入列而不会丢失数据。

假设CCDetails是我们要在 columnGlobaleNote之前插入列的表Sys_CreatedBy

declare @str1 nvarchar(1000)
declare @tableName nvarchar(1000)
set @tableName='CCDetails'
set @str1 = ''
SELECT @str1 = @str1 + ', ' + COLUMN_NAME
FROM Information_Schema.Columns
WHERE Table_Name = @tableName 
ORDER BY Ordinal_Position
set @str1 = right(@str1, len(@str1) - 2)
set @str1 = 'select ' + @str1 +'  into '+@tableName+'Temp from '+@tableName+' ; Drop Table '+ @tableName + ' ; EXEC sp_rename '+@tableName+'Temp, '+@tableName
set @str1 = REPLACE(@str1,'Sys_CreatedBy','CAST('''' as nvarchar(max)) As GlobaleNote , Sys_CreatedBy' )

exec sp_executesql @str1
于 2016-07-21T15:20:06.727 回答