以Sql Server的指定顺序返回插入的行

时间:2015-12-18 19:08:43

标签: sql-server

我需要按照指定的顺序从表值插入中返回行。

我可以使用OUTPUT INTO

DECLARE @generated1 TABLE ([Id] varbinary(8), [OwnerId] [int]);

INSERT INTO [Blog] ([OwnerId])
OUTPUT INSERTED.*
INTO @generated1
VALUES ('1'),
('2'),
('1'),
('2'),
('2'),
('3'),
('3'),
('3'),
('3');

SELECT * FROM @generated1;

这通常有效并返回

Id                  OwnerId
===========================
0x418B6EC7C6AC864D  1
0x6D0B89E56AB3EC48  2
0xE1B86C6A3C64AB42  1
0x51B8D9D1FCDE1647  2
0xB5AD578020CBCE4C  2
0x56CD3FF610080841  3
0x1D0D5B370A732C43  3
0x0B71CDB5CE6E0445  3
0x6A8AE3A2BD19924E  3

但是如果在OwnerId上定义了FK并且插入了超过125行,则插入它们的顺序与指定的顺序不同。

1 个答案:

答案 0 :(得分:2)

可以实现的一种方法是向要插入的每一行添加一个顺序值,将generated表与指定的值连接起来,并按添加的顺序值排序:

DECLARE @inserted1 TABLE ([Order] [int], [OwnerId] [int]);
INSERT INTO @inserted1
VALUES ('1', '1'),
('2', '2'),
('3', '1'),
('4', '3'),
('5', '2'),
('6', '3'),
('7', '3'),
('8', '2'),
('9', '3');

DECLARE @generated1 TABLE ([Id] varbinary(8), [OwnerId] [int]);
INSERT INTO [Blog] ([OwnerId])
OUTPUT INSERTED.[Id], INSERTED.[OwnerId]
INTO @generated1
SELECT [OwnerId] FROM @inserted1;

SELECT *
FROM (SELECT [g].[Id], [g].[OwnerId], [i].[Order]
FROM @generated1 [g]
INNER JOIN @inserted1 [i]
ON [g].[OwnerId] = [i].[OwnerId]) t
ORDER BY [Order];

但由于OwnerId不唯一,因此会产生比插入更多的行:

Id                  OwnerId Order
0x2557DCF354F9CD4E  1       1
0x3A265F70A2018249  1       1
0xA21503CD2F928144  2       2
0xE8C593480FCEAF41  2       2
0xC3E3C969BEA87641  2       2
0x2557DCF354F9CD4E  1       3
0x3A265F70A2018249  1       3
0x3F7EBD8EE702B44B  3       4
0xA3F09A3A612ACF41  3       4
0xA45D8F6FF779A74C  3       4
0x7BA9521290232D43  3       4
0xA21503CD2F928144  2       5
0xE8C593480FCEAF41  2       5
0xC3E3C969BEA87641  2       5
0x3F7EBD8EE702B44B  3       6
0xA3F09A3A612ACF41  3       6
0xA45D8F6FF779A74C  3       6
0x7BA9521290232D43  3       6
0x3F7EBD8EE702B44B  3       7
0xA3F09A3A612ACF41  3       7
0xA45D8F6FF779A74C  3       7
0x7BA9521290232D43  3       7
0xA21503CD2F928144  2       8
0xE8C593480FCEAF41  2       8
0xC3E3C969BEA87641  2       8
0x3F7EBD8EE702B44B  3       9
0xA3F09A3A612ACF41  3       9
0xA45D8F6FF779A74C  3       9
0x7BA9521290232D43  3       9

IdOrder列中仍然只有9个唯一值,但它们的组合方式无关紧要,因为标识该行的唯一值是OwnerId。诀窍是从结果中删除行,只返回9行,IdOrder中的值是唯一的。对两个列进行分区提供了一种确定性地对组合进行排序的方法:

SELECT *
FROM (SELECT [g].[Id], [g].[OwnerId], [i].[Order],
ROW_NUMBER() OVER (PARTITION BY [g].[Id] ORDER BY [i].[Order]) AS RowNumber,
ROW_NUMBER() OVER (PARTITION BY [i].[Order] ORDER BY [g].[Id]) AS RowNumber2
FROM @generated1 [g]
INNER JOIN @inserted1 [i]
ON [g].[OwnerId] = [i].[OwnerId]) t
WHERE RowNumber = RowNumber2
ORDER BY [Order];

这将按预期顺序返回行:

Id                  OwnerId Order   RowNumber   RowNumber2
======================================================
0x2A51E4E35D2FA040  1       1       1           1
0x787E303904EC764C  2       2       1           1
0x778CE142E9760248  1       3       2           2
0xC056C57F1729E643  3       4       1           1
0xC0706FF6A8890E40  2       5       2           2
0x0E2058F3F142DF42  3       6       2           2
0x4690B24BE196374B  3       7       3           3
0x9F70CA6011ECD449  2       8       3           3
0xF35D87D1BDB2C34F  3       9       4           4