我如何将 Insert 从 select 转换为 upsert
How can i convert Insert from select to upsert
如何将插入从 select 转换为更新插入。我有以下代码将数据从一个数据库 table 插入到另一个数据库,我能够插入到但如果某些内容更改了不属于 PK 的任何字段。 WITESTCO.dbo.[WIBOMD]
的主键是 [bomItem], [bomRev], [bomEntry]
。
INSERT INTO WITESTCO.dbo.[WIBOMD]
([bomItem], [bomRev], [bomEntry], [partId], [qty],[cmnt],[srcLoc],[dType],[lead],[lineNbr])
select
[STOCK NO]
, u.rev
, bomEntry = row_number() over (order by u.ordinal)
, u.Partid
, Qty='1'
, cmnt = 'TEST'
, srcLoc = 'TEST'
, dType = '0'
, lead = '0'
, lineNbr = row_number() over (order by u.ordinal)
from [inserted]
cross apply (values
([bomRev],1,[BOM-WHEEL PN])
,([bomRev],2,[BOM - RIM])
,([bomRev],3,[BOM - SECONDARY DISC PN])
,([bomRev],4,[BOM - FIN DISC PN])
,([bomRev],5, [BOM - FLAT FIN DISC PN])
,([bomRev],6,[WHL BOM PART 1 PN])
,([bomRev],7,[WHL BOM PART 2 PN])
,([bomRev],8,[WHL BOM PART 3 PN])
,([bomRev],9,[WHL BOM PART 4 PN])
,([bomRev],10,[WHL BOM PART 5 PN])
,([bomRev],11,[COLOR-PN])
) u (rev, ordinal, partId)
where nullif(u.partId,'') is not null AND NOT EXISTS(SELECT * FROM WITESTCO.dbo.[WIBOMD] WHERE WITESTCO.dbo.[WIBOMD].[bomItem]=inserted.[STOCK NO] and WITESTCO.dbo.[WIBOMD].[bomRev]=inserted.[RevControl]);
使用 common table expression 这样我们就可以在 not exists()
:
中包含 bomEntry
;with cte as (
select
[STOCK NO]
, u.rev
, bomEntry = row_number() over (order by u.ordinal)
, u.Partid
, Qty='1'
, cmnt = 'TEST'
, srcLoc = 'TEST'
, dType = '0'
, lead = '0'
, lineNbr = row_number() over (order by u.ordinal)
, RevControl
from [inserted]
cross apply (values
([bomRev],1,[BOM-WHEEL PN])
,([bomRev],2,[BOM - RIM])
,([bomRev],3,[BOM - SECONDARY DISC PN])
,([bomRev],4,[BOM - FIN DISC PN])
,([bomRev],5, [BOM - FLAT FIN DISC PN])
,([bomRev],6,[WHL BOM PART 1 PN])
,([bomRev],7,[WHL BOM PART 2 PN])
,([bomRev],8,[WHL BOM PART 3 PN])
,([bomRev],9,[WHL BOM PART 4 PN])
,([bomRev],10,[WHL BOM PART 5 PN])
,([bomRev],11,[COLOR-PN])
) u (rev, ordinal, partId)
where nullif(u.partId, '') is not null
)
INSERT INTO WITESTCO.dbo.[WIBOMD]
([bomItem], [bomRev], [bomEntry], [partId], [qty],[cmnt],[srcLoc],[dType],[lead],[lineNbr])
select
cte.[STOCK NO]
, cte.rev
, cte.bomEntry
, cte..Partid
, cte.Qty
, cte.cmnt
, cte.srcLoc
, cte.dType
, cte.lead
, cte.lineNbr
from cte
where not exists (
select 1
from WITESTCO.dbo.[WIBOMD] w
where w.[bomItem] = cte.[STOCK NO]
and w.[bomRev] = cte.[RevControl]
and w.[bomEntry]= cte.bomEntry
);
或者,您可以使用 subquery/derived table 代替常见的 table 表达式。
如果您使用的是 sql server 2008+,则可以使用 MERGE 语句 https://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql。
我在为您实施它时遇到了困难,但如果没有模式或不清楚您的数据是什么样子,这个解决方案第一次不太可能奏效。请更多地使用它作为概念证明而不是完全工作的代码。
MERGE WITESTCO.dbo.[WIBOMD] AS target
USING ( SELECT [STOCK NO]
, u.rev
, bomEntry = row_number() over (order by u.ordinal)
, u.Partid
, Qty ='1'
, cmnt = 'TEST'
, srcLoc = 'TEST'
, dType = '0'
, lead = '0'
, lineNbr = row_number() over (order by u.ordinal)
FROM [inserted]
CROSS APPLY ( VALUES ([bomRev],1,[BOM-WHEEL PN])
, ([bomRev],2,[BOM - RIM])
, ([bomRev],3,[BOM - SECONDARY DISC PN])
, ([bomRev],4,[BOM - FIN DISC PN])
, ([bomRev],5, [BOM - FLAT FIN DISC PN])
, ([bomRev],6,[WHL BOM PART 1 PN])
, ([bomRev],7,[WHL BOM PART 2 PN])
, ([bomRev],8,[WHL BOM PART 3 PN])
, ([bomRev],9,[WHL BOM PART 4 PN])
, ([bomRev],10,[WHL BOM PART 5 PN])
, ([bomRev],11,[COLOR-PN]) ) u (rev, ordinal, partId )
WHERE NULLIF(u.partId,'') is NOT NULL
AND NOT EXISTS ( SELECT *
FROM WITESTCO.dbo.[WIBOMD]
WHERE WITESTCO.dbo.[WIBOMD].[bomItem] = inserted.[STOCK NO]
AND WITESTCO.dbo.[WIBOMD].[bomRev] = inserted.[RevControl] )
) AS source ( [STOCK NO], rev, bomEntry, Partid, Qty, cmnt, srcLoc, dType, lead, lineNbr )
ON ( target.bomItem = source.[STOCK NO]
target.bomRev = source.Rev
target.bomEntry = source.bomEntry )
WHEN MATCHED THEN
UPDATE [bomItem] = [STOCK NO]
, [bomRev] = u.rev
, [bomEntry] = bomEntry
, [partId] = Partid
, [qty] = Qty
, [cmnt] = cmnt
, [srcLoc] = srcLoc
, [dType] = dType
, [lead] = lead
, [lineNbr] = lineNbr
WHEN NOT MATCHED THEN
INSERT ([bomItem], [bomRev], [bomEntry], [partId], [qty], [cmnt], [srcLoc], [dType], [lead], [lineNbr])
VALUES ([STOCK NO], rev, bomEntry, Partid, Qty, cmnt, srcLoc, dType, lead, lineNbr )
如何将插入从 select 转换为更新插入。我有以下代码将数据从一个数据库 table 插入到另一个数据库,我能够插入到但如果某些内容更改了不属于 PK 的任何字段。 WITESTCO.dbo.[WIBOMD]
的主键是 [bomItem], [bomRev], [bomEntry]
。
INSERT INTO WITESTCO.dbo.[WIBOMD]
([bomItem], [bomRev], [bomEntry], [partId], [qty],[cmnt],[srcLoc],[dType],[lead],[lineNbr])
select
[STOCK NO]
, u.rev
, bomEntry = row_number() over (order by u.ordinal)
, u.Partid
, Qty='1'
, cmnt = 'TEST'
, srcLoc = 'TEST'
, dType = '0'
, lead = '0'
, lineNbr = row_number() over (order by u.ordinal)
from [inserted]
cross apply (values
([bomRev],1,[BOM-WHEEL PN])
,([bomRev],2,[BOM - RIM])
,([bomRev],3,[BOM - SECONDARY DISC PN])
,([bomRev],4,[BOM - FIN DISC PN])
,([bomRev],5, [BOM - FLAT FIN DISC PN])
,([bomRev],6,[WHL BOM PART 1 PN])
,([bomRev],7,[WHL BOM PART 2 PN])
,([bomRev],8,[WHL BOM PART 3 PN])
,([bomRev],9,[WHL BOM PART 4 PN])
,([bomRev],10,[WHL BOM PART 5 PN])
,([bomRev],11,[COLOR-PN])
) u (rev, ordinal, partId)
where nullif(u.partId,'') is not null AND NOT EXISTS(SELECT * FROM WITESTCO.dbo.[WIBOMD] WHERE WITESTCO.dbo.[WIBOMD].[bomItem]=inserted.[STOCK NO] and WITESTCO.dbo.[WIBOMD].[bomRev]=inserted.[RevControl]);
使用 common table expression 这样我们就可以在 not exists()
:
bomEntry
;with cte as (
select
[STOCK NO]
, u.rev
, bomEntry = row_number() over (order by u.ordinal)
, u.Partid
, Qty='1'
, cmnt = 'TEST'
, srcLoc = 'TEST'
, dType = '0'
, lead = '0'
, lineNbr = row_number() over (order by u.ordinal)
, RevControl
from [inserted]
cross apply (values
([bomRev],1,[BOM-WHEEL PN])
,([bomRev],2,[BOM - RIM])
,([bomRev],3,[BOM - SECONDARY DISC PN])
,([bomRev],4,[BOM - FIN DISC PN])
,([bomRev],5, [BOM - FLAT FIN DISC PN])
,([bomRev],6,[WHL BOM PART 1 PN])
,([bomRev],7,[WHL BOM PART 2 PN])
,([bomRev],8,[WHL BOM PART 3 PN])
,([bomRev],9,[WHL BOM PART 4 PN])
,([bomRev],10,[WHL BOM PART 5 PN])
,([bomRev],11,[COLOR-PN])
) u (rev, ordinal, partId)
where nullif(u.partId, '') is not null
)
INSERT INTO WITESTCO.dbo.[WIBOMD]
([bomItem], [bomRev], [bomEntry], [partId], [qty],[cmnt],[srcLoc],[dType],[lead],[lineNbr])
select
cte.[STOCK NO]
, cte.rev
, cte.bomEntry
, cte..Partid
, cte.Qty
, cte.cmnt
, cte.srcLoc
, cte.dType
, cte.lead
, cte.lineNbr
from cte
where not exists (
select 1
from WITESTCO.dbo.[WIBOMD] w
where w.[bomItem] = cte.[STOCK NO]
and w.[bomRev] = cte.[RevControl]
and w.[bomEntry]= cte.bomEntry
);
或者,您可以使用 subquery/derived table 代替常见的 table 表达式。
如果您使用的是 sql server 2008+,则可以使用 MERGE 语句 https://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql。
我在为您实施它时遇到了困难,但如果没有模式或不清楚您的数据是什么样子,这个解决方案第一次不太可能奏效。请更多地使用它作为概念证明而不是完全工作的代码。
MERGE WITESTCO.dbo.[WIBOMD] AS target
USING ( SELECT [STOCK NO]
, u.rev
, bomEntry = row_number() over (order by u.ordinal)
, u.Partid
, Qty ='1'
, cmnt = 'TEST'
, srcLoc = 'TEST'
, dType = '0'
, lead = '0'
, lineNbr = row_number() over (order by u.ordinal)
FROM [inserted]
CROSS APPLY ( VALUES ([bomRev],1,[BOM-WHEEL PN])
, ([bomRev],2,[BOM - RIM])
, ([bomRev],3,[BOM - SECONDARY DISC PN])
, ([bomRev],4,[BOM - FIN DISC PN])
, ([bomRev],5, [BOM - FLAT FIN DISC PN])
, ([bomRev],6,[WHL BOM PART 1 PN])
, ([bomRev],7,[WHL BOM PART 2 PN])
, ([bomRev],8,[WHL BOM PART 3 PN])
, ([bomRev],9,[WHL BOM PART 4 PN])
, ([bomRev],10,[WHL BOM PART 5 PN])
, ([bomRev],11,[COLOR-PN]) ) u (rev, ordinal, partId )
WHERE NULLIF(u.partId,'') is NOT NULL
AND NOT EXISTS ( SELECT *
FROM WITESTCO.dbo.[WIBOMD]
WHERE WITESTCO.dbo.[WIBOMD].[bomItem] = inserted.[STOCK NO]
AND WITESTCO.dbo.[WIBOMD].[bomRev] = inserted.[RevControl] )
) AS source ( [STOCK NO], rev, bomEntry, Partid, Qty, cmnt, srcLoc, dType, lead, lineNbr )
ON ( target.bomItem = source.[STOCK NO]
target.bomRev = source.Rev
target.bomEntry = source.bomEntry )
WHEN MATCHED THEN
UPDATE [bomItem] = [STOCK NO]
, [bomRev] = u.rev
, [bomEntry] = bomEntry
, [partId] = Partid
, [qty] = Qty
, [cmnt] = cmnt
, [srcLoc] = srcLoc
, [dType] = dType
, [lead] = lead
, [lineNbr] = lineNbr
WHEN NOT MATCHED THEN
INSERT ([bomItem], [bomRev], [bomEntry], [partId], [qty], [cmnt], [srcLoc], [dType], [lead], [lineNbr])
VALUES ([STOCK NO], rev, bomEntry, Partid, Qty, cmnt, srcLoc, dType, lead, lineNbr )