这就是我想要做的事情:
我们说我有两张桌子dbo.source& dbo.destination 我希望将所有记录从源复制到目标,如果目标中不存在某个自然键(唯一的非群集)。如果插入成功,则将一些值输出到临时缓冲表。 接下来我想列出来自DID在目的地中匹配的来源的所有记录,并将这些记录复制到缓冲表中。
无论如何我可以实现这一点,以便缓冲表不能保存冗余数据吗?
这是我目前的逻辑:
步骤1:从源表中获取自然键与目标不匹配的记录并插入目标 将这些插入带有标志
的缓冲区表中MERGE INTO dbo.Destination dest USING dbo.Source AS src
ON dest.Name = src.Name --Natural Key
WHEN NOT MATCHED THEN
INSERT (xxx) VALUES (xxx)
OUTPUT src.ID, Inserted.ID, 'flagA'
INTO dbo.Buffer;
步骤2: 从源表中获取自然键与目标匹配的记录 将这些插入缓冲区并带有标志
Insert INTO dbo.Buffer
Select src.ID, src.Name, 'flagB'
FROM dbo.Source src
inner join dbo.Destination dest
on src.Name = dest.Name
有了这个逻辑,我在我的缓冲区中获得了多余的行,这些行并没有按预期精确地跟踪插入。任何人都可以基于我想要做的事情批评我的SQL。
答案 0 :(得分:3)
你可以尝试一下这样的技巧,不喜欢这种技术就是你总是更新一个字段。也许,你需要根据自己的需要调整我的例子。
Redux
结果
目的地表
DECLARE @Source table (id int identity , myValue varchar(5))
DECLARE @Destination table (id int identity , myValue varchar(5))
DECLARE @Buffer table (sourceId int , InsertId varchar(5),flag varchar(5))
insert @Source (myValue) values ( 'a') ,( 'e'),( 'i'),( 'o'),( 'u')
insert @Destination (myValue) values ('a') ,('b'),('c')
;merge @Destination t
using @Source S
on
t.myValue = s.myValue
when not matched then insert (myValue) values (s.myValue)
when matched then update set myValue = t.myValue
output s.id, inserted.id, case $action when 'INSERT' then 'flagA' else 'flagB' end into @Buffer;
select * from @Destination
select * from @Buffer
缓冲表
id myValue
----------- -------
1 a
2 b
3 c
4 e
5 i
6 o
7 u
使用此输出
sourceId InsertId flag
----------- -------- -----
2 4 flagA
3 5 flagA
4 6 flagA
5 7 flagA
1 1 flagB
的
output s.id, case $action when 'INSERT' then Cast(inserted.id as varchar(5)) else inserted.myValue end , case $action when 'INSERT' then 'flagA' else 'flagB' end into @Buffer;
答案 1 :(得分:2)
运行第二个查询时,它也匹配刚刚插入的行。你应该这样做:
Insert INTO dbo.Buffer
Select src.ID, src.name, 'flagB'
FROM dbo.Source src
inner join dbo.Destination dest on src.Name = dest.Name
where not exists (
select * from dbo.Buffer b where b.xxx = 'flagA' and b.yyy = src.name
)
或者只是在与目标匹配时使用,如LONG建议的那样。