我在做一个项目时,发现了使用SELECT INTO语句时的一些有趣行为。如果我有一个表格,并且其中一个列被定义为int identity(1,1) not null
,并使用SELECT INTO进行复制,则新表将保留该IDENTITY属性,除非涉及到JOIN操作。如果存在JOIN操作,则新表中的同一列仅被定义为int not null
。
以下是一个脚本,您可以运行它以重现这种行为:
CREATE TABLE People (Id INT IDENTITY(1,1) not null, Name VARCHAR(10))
CREATE TABLE ReverseNames (Name varchar(10), ReverseName varchar(10))
INSERT INTO People (Name)
VALUES ('John'), ('Jamie'), ('Joe'), ('Jenna')
INSERT INTO ReverseNames (Name, ReverseName)
VALUES ('John','nhoJ'), ('Jamie','eimaJ'), ('Joe','eoJ'), ('Jenna','anneJ')
--------
SELECT Id, Name
INTO People_ExactCopy
FROM People
SELECT Id, ReverseName as Name
INTO People_WithJoin
FROM People
JOIN ReverseNames
ON People.Name = ReverseNames.Name
SELECT Id, (SELECT ReverseName FROM ReverseNames WHERE Name = People.Name) as Name
INTO People_WithSubSelect
FROM People
--------
SELECT OBJECT_NAME(c.object_id) as [Table],
c.is_identity as [Id Column Retained Identity]
FROM sys.columns c
where
OBJECT_NAME(c.object_id) IN ('People_ExactCopy','People_WithJoin','People_WithSubSelect')
AND c.name = 'Id'
--------
DROP TABLE People
DROP TABLE People_ExactCopy
DROP TABLE People_WithJoin
DROP TABLE People_WithSubSelect
DROP TABLE ReverseNames
我注意到WithJoin和WithSubSelect查询的执行计划都包含了一个联接操作符。如果我们处理更大的行集,不确定哪个性能更好。
有人能否解释一下,并告诉我是否有办法在联接中利用SELECT INTO并仍然保留IDENTITY属性?
SELECT INTO
语句相当于使用 Justin 的示例中的SET IDENTITY_INSERT ON
。如果在SELECT INTO
之前执行DELETE FROM People where Name = 'Jamie'
,则 Joe 和 Jamie 保留了 ID 为 3 和 4。使用 INDENTITY 函数将无法保留这些 ID。您每 5 秒钟才能编辑一次评论。(单击此框以关闭) - Conrad Frix