在表中插入多行时,是否可以保证它们按照我指定的顺序进入?例如,请采取以下措施:
DECLARE @blah TABLE
(
ID INT IDENTITY(1, 1),
Name VARCHAR(100) NOT NULL
);
INSERT INTO @blah (Name)
VALUES('Timmy'),
('Jonny'),
('Sally');
SELECT * FROM @blah
是否可以保证Sally
的主键比Timmy
更高?
答案 0 :(得分:6)
以前曾问过非常相似的question。
您可以在ORDER BY
中指定INSERT
。
如果这样做,生成IDENTITY
值的顺序将保证与ORDER BY
中指定的INSERT
匹配。
使用您的示例:
DECLARE @blah TABLE
(
ID INT IDENTITY(1, 1) NOT NULL,
Name VARCHAR(100) NOT NULL
);
INSERT INTO @blah (Name)
SELECT T.Name
FROM
(
VALUES
('Timmy'),
('Jonny'),
('Sally')
) AS T(Name)
ORDER BY T.Name;
SELECT
T.ID
,T.Name
FROM @blah AS T
ORDER BY T.ID;
结果是:
+----+-------+
| ID | Name |
+----+-------+
| 1 | Jonny |
| 2 | Sally |
| 3 | Timmy |
+----+-------+
即,已对Name
进行了排序,并根据此顺序生成了ID。保证Jonny将拥有最低ID,Timmy将拥有最高ID,Sally将拥有他们之间的ID。生成的ID值之间可能存在间隙,但它们的相对顺序是有保证的。
如果您未在ORDER BY
中指定INSERT
,则可以按不同的顺序生成生成的IDENTITY
ID。
请注意,即使在ORDER BY
中使用INSERT
,也无法保证表中行的实际物理顺序,唯一的保证是生成的ID。
问题INSERT INTO as SELECT with ORDER BY来自MS的Umachandar Jayachandran说:
唯一的保证是将生成身份值 在ORDER BY子句中。但是不能保证秩序 将行插入表中。
他给了Ordering guarantees in SQL Server的链接,来自SQL Server Engine团队的Conor Cunningham说:
- 使用SELECT和ORDER BY来填充行的INSERT查询保证了如何计算标识值,但不保证计算标识值的顺序 插入行
醇>
在该帖子的评论中有一个指向MS知识库文章的链接:The behavior of the IDENTITY function when used with SELECT INTO or INSERT .. SELECT queries that contain an ORDER BY clause,它更详细地解释了它。它说:
如果您希望以顺序方式分配
IDENTITY
值 遵循ORDER BY
子句中的顺序,创建一个表 包含具有IDENTITY
属性的列,然后运行INSERT ... SELECT ... ORDER BY
查询以填充此表。
我会将此知识库文章视为官方文档,并认为此行为得到保证。
答案 1 :(得分:0)
您最好的两个选择是:
单独处理行 - 插入父行,获取ID,然后插入子项,然后插入下一个父行等。
或者,假设数据在现实世界中具有实际标识符(例如,电子邮件地址,SSN等),那么您可以在插入子表时使用它来连接回父表。
答案 2 :(得分:0)
不,这不能保证。这相当于
INSERT INTO @blah (Name)
SELECT *
FROM (VALUES ('Timmy'),
('Jonny'),
('Sally')) x(y)
FROM
子句只是一个无序集。
您可以引入一列作为唯一键:
INSERT INTO @blah (Name)
OUTPUT RowNum, INSERTED.ID
SELECT Name
FROM (VALUES (1, 'Timmy'),
(2, 'Jonny'),
(3, 'Sally')) x(RowNum, Name)
然后,您可以使用RowNum
唯一标识行,并将其与生成的ID进行匹配。
可能INSERT
语句不允许输出非插入列。您可以使用MERGE
。