以前一直以为在SQL SERVER中,在表的列中间插入新列与在表的最后面添加一列,这两者应该是一样的。今天特意为这两者做了对比,分析如下:
我们先创建一个简单的表,用来做分析:
CREATE TABLE [dbo].[Table_1](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
然后在Microsoft SQL Server Management Studio中在该表的ID列与Name列中插入varchar(50)列UserID,然后点击生成更改脚本,生成的脚本如下:
/* 为了防止任何可能出现的数据丢失问题,您应该先仔细检查此脚本,然后再在数据库设计器的上下文之外运行此脚本。*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_Table_1
(
ID int NOT NULL IDENTITY (1, 1),
UserID varchar(50) NULL,
Name varchar(50) NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT dbo.Tmp_Table_1 ON
GO
IF EXISTS(SELECT * FROM dbo.Table_1)
EXEC('INSERT INTO dbo.Tmp_Table_1 (ID, Name)
SELECT ID, Name FROM dbo.Table_1 WITH (HOLDLOCK TABLOCKX)')
GO
SET IDENTITY_INSERT dbo.Tmp_Table_1 OFF
GO
DROP TABLE dbo.Table_1
GO
EXECUTE sp_rename N'dbo.Tmp_Table_1', N'Table_1', 'OBJECT'
GO
COMMIT
可以看出来,SQL SERVER是先将插入后的列和原有的列一起创建了一个新的表Tmp_Table_1,然后设置IDENTITY_INSERT为on,即开启自增量显式插入,再将Table_1的数据复制到Tmp_Table_1中,然后关闭自增量显式插入,再然后删除dbo.Table_1,最后修改dbo.Tmp_Table_1表名为dbo._Table_1。
关于IDENTITY_INSERT的具体用法,请参见本站:
往自增列插入显式值-SET IDENTITY_INSERT详解这其中涉及的步骤很多,如果为该表创建了触发器,约束等,情况就更加复杂了,而且在数据转移的过程中,容易造成数据错误。
我们再测试直接在表的最后一列Name后追加varchar(50)列UserID,然后点击生成更改脚本,生成的脚本如下:
/* 为了防止任何可能出现的数据丢失问题,您应该先仔细检查此脚本,然后再在数据库设计器的上下文之外运行此脚本。*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Table_1 ADD
UserID varchar(50) NULL
GO
COMMIT
可以看出来,这样SQL SERVER执行的SQL非常简单,直接就Alter表了,不会发生数据转移与创建临时表等情况,当然也不会造成数据转移错误了。
所以,如果不是有特别的要求,在表中添加新列时,我们强烈推荐直接在表尾添加,而不是在表中间插入新的列。m