我觉得我大部分知道如何做到这一点,而不是如何加入它。
我会试着合理地解决这个问题:
我有3张桌子:
SliderId
我将值放入TestA:
Store.Slider
现在,当我将TestA中的行(实际上只是TestVal列值)移动到TestB时,我想向Audit添加一行,其中包含A中的主键以及B中的相应主键(其中值为正在进行中) - 然后删除A中的行。这就是我所拥有的:
CREATE TABLE [dbo].[TestA] ([PrimaryKey] [int],[TestVal] [int]);
CREATE TABLE [dbo].[TestB] ([PrimaryKey] [int],[TestVal] [int]);
CREATE TABLE [dbo].[Audit] ([PrimaryKey] [int],[SourcePrimaryKey] [int],[DestinationPrimaryKey] [int]);
所以我创建了这个临时表@pk,它可以准确地获取目标主键(因为它们在b中结束),但是我无法弄清楚如何将它们与主键进行结合在A.读取MSDN时,OUTPUT函数不一定可靠地顺序排列,所以我不能只假设来自testa的SELECT主键,其中testval> 2会产生相同的订单。
有什么想法吗?
答案 0 :(得分:1)
注意:我还没有对这个问题评估MERGE方法......但我不喜欢MERGE用于非常大的数据集,因为它在大多数情况下表现不佳(与单独的DELETE / INSERT / UPDATE相比,尤其是对于列存储索引)。所以我建议其他方法。
方法1(简单)。您可以将SourcePK INT添加到TestB表并在INSERT中填充它。然后在输出中使用SourcePK和TargetPK填充Audit表,并且您不需要临时表。
方法2(差)。如果您不能将第二列添加到TestB中,但您可以将TestVal的数据类型从INT更改为BIGINT,则可以使用按位移位和按位OR / AND将SourcePK保存在TestVal中。然后,对于TestVal的每次使用,您只需要使用其一半的位。我不喜欢这种方法,因此实施(1)
更好方法3(谨慎使用)。您可以为目标表生成PK列表,并将其映射到每个SourceID。您不需要OUTPUT,因为您只需使用映射的SourceID / TargetID执行第二次INSERT到Audit。但是您需要确保没有将数据插入目标表的并发进程。即使有并发性也有解决方法 - 您可以重新设置标识,并使用SET IDENTITY_INSERT插入范围或使用某些锁定机制
答案 1 :(得分:0)
--Create tables
DECLARE @TestA TABLE
([PrimaryKey] INT IDENTITY,
[TestVal] INT
);
DECLARE @TestB TABLE
([PrimaryKey] INT IDENTITY,
[TestVal] INT
);
DECLARE @Audit TABLE
([PrimaryKey] INT IDENTITY,
[SourcePrimaryKey] INT,
[DestinationPrimaryKey] INT
);
--Insert Values
INSERT INTO @TestA([TestVal])
VALUES(1), (2), (3), (4), (5);
--Temp table to hold key values
DECLARE @pk TABLE(b INT);
--Insert into TestB
INSERT INTO @testB(TestVal)
OUTPUT inserted.PrimaryKey
INTO @pk
SELECT TestVal
FROM @testA ta
WHERE ta.testVal > 2;
--Display what we have so far
SELECT *
FROM @TestA;
SELECT *
FROM @TestB;
SELECT *
FROM @pk;
--Insert into audit table
INSERT INTO @Audit
(SourcePrimaryKey,
DestinationPrimaryKey
)
SELECT ta.PrimaryKey,
tb.PrimaryKey
FROM @TestB tb
JOIN @PK pk ON tb.PrimaryKey = pk.b
JOIN @TestA ta ON tb.TestVal = ta.TestVal; --Is test value always going to be Unque?
--Delete from testA table
DELETE FROM @TestA
WHERE TestVal IN(SELECT TestVal
FROM @TestB tb
JOIN @PK pk ON tb.PrimaryKey = pk.b);
--Display what we have
SELECT *
FROM @TestA;
SELECT *
FROM @TestB;
SELECT *
FROM @pk;