SQL Server - 更改表与删除和创建
-
28-09-2020 - |
题
我们的数据库是SQL Server 2008 R2。我们有一些表,其中有一些 varchar(500) 列,我想将它们切换到 datetime2 或 bigint。我可以保证要切换的列中的所有数据对于正确的类型都是有效的。列更改确实会影响索引,但不会影响键。
在与同事讨论时,我们得出了两种解决该问题的方法。这两个操作都可以通过 T-Sql 脚本完成。
- 通过 select into 创建临时表,删除旧表并使用正确的数据类型重新创建表。重新创建索引。
- 通过更改当前表/数据类型
ALTER TABLE x ALTER COLUMN Y datetime2
然后重建或重新创建索引。
因为我相信数据会干净地转换,所以我倾向于#2。我的同事和一位 DBA 朋友更喜欢#1,但我的同事不记得为什么要这样训练他。DBA 朋友正在度假,所以我没有问他原因。
有人可以提供他们认为更好的选项以及为什么的见解吗?最终这是我的决定,我想知道为什么#1 会比#2 更受青睐?
解决方案
我最近在我的组织中这样做了,我们想要处理一个包含十亿多行的表。
这个想法的所有功劳都归功于 Aaron Bertrand,并且来自他的博客文章 技巧射击:模式切换-A-Roo
在小桌子上测试以下过程,并在 PROD 中进行操作之前让自己感到舒服。
- 创建2个模式
fake
和shadow
经授权dbo
. - 创建一个包含所需列和数据类型的表
shadow
模式例如create table shadow.Correct_Table ...
- 插入数据并创建原表有的所有索引
shadow
模式表。 - 这样,您就可以拥有包含数据和索引的相同表副本,但它们位于不同的架构中(逻辑上分离)。
- 完成后更新表上的统计信息
shadow
架构。 切换模式(这是元数据操作并且速度非常快)
--- ALTER SCHEMA TargetSchema TRANSFER SourceSchema.TableName; BEGIN TRANSACTION; ALTER SCHEMA fake TRANSFER dbo.original_table; ALTER SCHEMA dbo TRANSFER shadow.Correct_Table; COMMIT TRANSACTION; ALTER SCHEMA shadow TRANSFER fake.Lookup;
进行最后检查,看看一切是否按计划进行。你应该做一个
select count(1) from dbo.Correct_table
确认第 7 步并且您满意后,请放弃
shadow.table
,shadow
模式和fake
架构作为清理。
其他提示
这是我的看法。
#1 的优点
- 由于您使用的是单独的表,因此您的生产表将一直处于使用状态,直到您完成为止。没有锁(除了读取数据所需的锁)。
- 这也符合@AaronBertrand 所说的:你可以零碎地做,测试等
- 您可以根据需要更改列顺序
#2 的优点
- 这是一个全有或全无的操作。当您没有查看时,您不可能丢失在原始表中插入/修改的数据。
- 保留专门分配给该对象的任何权限。如果您使用#1,您必须确保编写脚本并应用它们。
话虽这么说,我通常会在小表或可能发生中断时使用#2(不过,总是事先进行备份),如果我无法得到那么大的中断或者我必须重新安排,则使用#1列顺序等如果我要做#1,我通常会通过 GUI 生成脚本,然后在运行之前仔细检查它。
请小心删除并重新创建选项:这可能会使 sys.depends 处于奇怪的状态,并导致列的顺序或类型发生变化的缓存计划出现问题。
您还需要采取措施维护任何对象级别权限,因为这些权限将在 DROP
并且不会自动重新创建后续的 CREATE
.
ALTER TABLE
在我看来,是更干净的选项,但请确保在生产中执行之前进行彻底测试,以确保之后一切顺利,并确保您知道操作将花费多长时间(对于包含许多行的表,这可能会花费相当长的时间) )。
我的同事最终找到了一篇关于他所指内容的文章: http://www.nigelrivett.net/SQLAdmin/AlterTableProblems.html. 。阅读本文并意识到我们的年终报告即将发布后,我们决定不对列类型进行更改,并将在接下来的几个月内重新审视这一点。我想读完这篇文章后,我可能会选择 Drop/Create 方法。
感谢大家对此的反馈。当我们决定继续前进时,需要考虑许多有趣的方法。