我有两个表,每个表有30多列。我需要比较表并找到那些
的行我很难完成这项工作。我尝试过使用Union All来比较两张桌子。使用表A和B,我得到
的所有行我已经使用了SQL的except
函数,我可以从A中获取不在B中的所有行或从B中不在A中的所有行。
我有一个根据this博客文章执行UNION ALL
的SP。然后,我发现Except
用于获取两个表的差异并尝试过。然而,我无法实现我的目标。我最终要做的是我在A中的数据需要根据表B中的内容进行更新/删除/添加。我希望能够比较2表和
任何帮助或建议都将不胜感激。
编辑3
在与我的团队交谈后,我有一个4列匹配,我可以确定哪些行应该相同。它是PONumber,POLineNumber,IMLineNumber和ProjectNumber(按此顺序),因为我没有公共ID,所以我会匹配。
修改
两个表中都没有主键。我应该首先添加这个,但在看到下面的评论和答案之前没有想到它。我必须根据行中的数据而不是特定键来匹配所有内容。我明天会在这里得到表数据地图。
这是我到目前为止所得到的:
insert into working.ComparedMaterialTrackingTables(TableName
,State
,ProjectNumber
,SubProjectNumber
,PONumber
,POLineNumber
,IMLineNumber
,CalloutDetails
,POStatus
,BlanketRelease
,PODateIssued
,DateNeeded
,POInvoiceStatus
,ItemCode
,ItemDesc
,QuantityOrdered
,QuantityReceived
,DateReceived
,RecordStatus
,ShipToLocation
,DeliverToLocation
,ReceiverId
,TraceNumber
,BOL
,PackSlipNumber
,POTotalAmount
,POLineAmount
,CostCode
,RequisitionId
,RequisitionLineNumber
,Vendor
,ExchangeName
,ProjectType
,COECurrentProjectStatus
,ReadyForService
,ScheduledShipDate
,MaterialComments
,SchedulerComments
,MaterialSpecialist)
exec spCompareTables @Table1='TestingTable', @Table2='working.MaterialTracking'
, @T1Columns='State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,CalloutDetails,POStatus,BlanketRelease,PODateIssued,DateNeeded
,POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,QuantityReceived,DateReceived,RecordStatus,ShipToLocation,DeliverToLocation,ReceiverId
,TraceNumber,BOL,PackSlipNumber,POTotalAmount,POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,ProjectType
,COECurrentProjectStatus,ReadyForService,ScheduledShipDate,MaterialComments,SchedulerComments,MaterialSpecialist'
begin tran --commit rollback
create table #MaterialID(ID int)
insert into #MaterialID(ID)
select tt.woid from working.MaterialTracking tt
join (select State
,ProjectNumber
,SubProjectNumber
,PONumber
,POLineNumber
,IMLineNumber
,CalloutDetails
,POStatus
,BlanketRelease
,PODateIssued
,DateNeeded
,POInvoiceStatus
,ItemCode
,ItemDesc
,QuantityOrdered
,QuantityReceived
,DateReceived
,RecordStatus
,ShipToLocation
,DeliverToLocation
,ReceiverId
,TraceNumber
,BOL
,PackSlipNumber
,POTotalAmount
,POLineAmount
,CostCode
,RequisitionId
,RequisitionLineNumber
,Vendor
,ExchangeName
,ProjectType
,COECurrentProjectStatus
,ReadyForService
,ScheduledShipDate
,MaterialComments
,SchedulerComments
,MaterialSpecialist
from working.MaterialTracking
Except
select State
,ProjectNumber
,SubProjectNumber
,PONumber
,POLineNumber
,IMLineNumber
,CalloutDetails
,POStatus
,BlanketRelease
,PODateIssued
,DateNeeded
,POInvoiceStatus
,ItemCode
,ItemDesc
,QuantityOrdered
,QuantityReceived
,DateReceived
,RecordStatus
,ShipToLocation
,DeliverToLocation
,ReceiverId
,TraceNumber
,BOL
,PackSlipNumber
,POTotalAmount
,POLineAmount
,CostCode
,RequisitionId
,RequisitionLineNumber
,Vendor
,ExchangeName
,ProjectType
,COECurrentProjectStatus
,ReadyForService
,ScheduledShipDate
,MaterialComments
,SchedulerComments
,MaterialSpecialist
from TestingTable) ctt on ctt.State = tt.State
and ctt.ProjectNumber = tt.ProjectNumber
and ctt.SubProjectNumber = tt.SubProjectNumber
and ctt.PONumber = tt.PONumber
and ctt.POLineNumber = tt.POLineNumber
and ctt.IMLineNumber = tt.IMLineNumber
and ctt.POStatus = tt.POStatus
and ctt.BlanketRelease = tt.BlanketRelease
and ctt.PODateIssued = tt.PODateIssued
and ctt.DateNeeded = tt.DateNeeded
and ctt.POInvoiceStatus = tt.POInvoiceStatus
and ctt.ItemCode = tt.ItemCode
and ctt.ItemDesc = tt.ItemDesc
and ctt.QuantityOrdered = tt.QuantityOrdered
and ctt.ShipToLocation = tt.ShipToLocation
and ctt.DeliverToLocation = tt.DeliverToLocation
and ctt.TraceNumber = tt.TraceNumber
and ctt.BOL = tt.BOL
and ctt.PackSlipNumber = tt.PackSlipNumber
and ctt.POTotalAmount = tt.POTotalAmount
and ctt.POLineAmount = tt.POLineAmount
and ctt.CostCode = tt.CostCode
and ctt.RequisitionId = tt.RequisitionId
and ctt.RequisitionLineNumber = tt.RequisitionLineNumber
and ctt.Vendor = tt.Vendor
and ctt.ExchangeName = tt.ExchangeName
and ctt.COECurrentProjectStatus = tt.COECurrentProjectStatus
and ctt.ReadyForService = tt.ReadyForService
and ctt.MaterialSpecialist = tt.MaterialSpecialist
and ctt.QuantityReceived = tt.QuantityReceived
and ctt.DateReceived = tt.DateReceived
and ctt.ReceiverId = tt.ReceiverId
and ctt.ScheduledShipDate = tt.ScheduledShipDate
and ctt.CalloutDetails = tt.CalloutDetails
and ctt.ProjectType = tt.ProjectType
and ctt.RecordStatus = tt.RecordStatus
and ctt.MaterialComments = tt.MaterialComments
and ctt.SchedulerComments = tt.SchedulerComments
insert into TestingTable (State
,ProjectNumber
,SubProjectNumber
,PONumber
,POLineNumber
,IMLineNumber
,CalloutDetails
,POStatus
,BlanketRelease
,PODateIssued
,DateNeeded
,POInvoiceStatus
,ItemCode
,ItemDesc
,QuantityOrdered
,QuantityReceived
,DateReceived
,RecordStatus
,ShipToLocation
,DeliverToLocation
,ReceiverId
,TraceNumber
,BOL
,PackSlipNumber
,POTotalAmount
,POLineAmount
,CostCode
,RequisitionId
,RequisitionLineNumber
,Vendor
,ExchangeName
,ProjectType
,COECurrentProjectStatus
,ReadyForService
,ScheduledShipDate
,MaterialComments
,SchedulerComments
,MaterialSpecialist)
select State
,ProjectNumber
,SubProjectNumber
,PONumber
,POLineNumber
,IMLineNumber
,CalloutDetails
,POStatus
,BlanketRelease
,PODateIssued
,DateNeeded
,POInvoiceStatus
,ItemCode
,ItemDesc
,QuantityOrdered
,QuantityReceived
,DateReceived
,RecordStatus
,ShipToLocation
,DeliverToLocation
,ReceiverId
,TraceNumber
,BOL
,PackSlipNumber
,POTotalAmount
,POLineAmount
,CostCode
,RequisitionId
,RequisitionLineNumber
,Vendor
,ExchangeName
,ProjectType
,COECurrentProjectStatus
,ReadyForService
,ScheduledShipDate
,MaterialComments
,SchedulerComments
,MaterialSpecialist
from working.MaterialTracking
Except
select State
,ProjectNumber
,SubProjectNumber
,PONumber
,POLineNumber
,IMLineNumber
,CalloutDetails
,POStatus
,BlanketRelease
,PODateIssued
,DateNeeded
,POInvoiceStatus
,ItemCode
,ItemDesc
,QuantityOrdered
,QuantityReceived
,DateReceived
,RecordStatus
,ShipToLocation
,DeliverToLocation
,ReceiverId
,TraceNumber
,BOL
,PackSlipNumber
,POTotalAmount
,POLineAmount
,CostCode
,RequisitionId
,RequisitionLineNumber
,Vendor
,ExchangeName
,ProjectType
,COECurrentProjectStatus
,ReadyForService
,ScheduledShipDate
,MaterialComments
,SchedulerComments
,MaterialSpecialist
from TestingTable
delete from working.MaterialTracking
from working.MaterialTracking mt
join #MaterialID mi on mi.ID = mt.WOID
编辑2 这是working.MaterialTracking表的表数据:
TABLE_NAME COLUMN_NAME IS_NULLABLE DATA_TYPE
MaterialTracking ID NO uniqueidentifier
MaterialTracking State YES nvarchar
MaterialTracking ProjectNumber YES nvarchar
MaterialTracking SubProjectNumber YES nvarchar
MaterialTracking PONumber YES nvarchar
MaterialTracking POLineNumber YES int
MaterialTracking IMLineNumber YES nvarchar
MaterialTracking CalloutDetails YES nvarchar
MaterialTracking POStatus YES nvarchar
MaterialTracking BlanketRelease YES int
MaterialTracking PODateIssued YES datetime
MaterialTracking DateNeeded YES datetime
MaterialTracking POInvoiceStatus YES nvarchar
MaterialTracking ItemCode YES nvarchar
MaterialTracking ItemDesc YES nvarchar
MaterialTracking QuantityOrdered YES numeric
MaterialTracking QuantityReceived YES numeric
MaterialTracking DateReceived YES nvarchar
MaterialTracking RecordStatus YES varchar
MaterialTracking ShipToLocation YES nvarchar
MaterialTracking DeliverToLocation YES nvarchar
MaterialTracking ReceiverId YES nvarchar
MaterialTracking TraceNumber YES nvarchar
MaterialTracking BOL YES nvarchar
MaterialTracking PackSlipNumber YES nvarchar
MaterialTracking POTotalAmount YES numeric
MaterialTracking POLineAmount YES numeric
MaterialTracking CostCode YES nvarchar
MaterialTracking RequisitionId YES nvarchar
MaterialTracking RequisitionLineNumber YES int
MaterialTracking Vendor YES nvarchar
MaterialTracking ExchangeName YES nvarchar
MaterialTracking ProjectType YES nvarchar
MaterialTracking COECurrentProjectStatus YES nvarchar
MaterialTracking ReadyForService YES datetime
MaterialTracking ScheduledShipDate YES nvarchar
MaterialTracking MaterialComments YES nvarchar
MaterialTracking SchedulerComments YES nvarchar
MaterialTracking MaterialSpecialist YES nvarchar
MaterialTracking woid NO int
这里是TestingTable:
TABLE_NAME COLUMN_NAME IS_NULLABLE DATA_TYPE
TestingTable State YES nvarchar
TestingTable ProjectNumber YES nvarchar
TestingTable SubProjectNumber YES nvarchar
TestingTable PONumber YES nvarchar
TestingTable POLineNumber YES int
TestingTable IMLineNumber YES nvarchar
TestingTable POStatus YES nvarchar
TestingTable BlanketRelease YES int
TestingTable PODateIssued YES datetime
TestingTable DateNeeded YES datetime
TestingTable POInvoiceStatus YES nvarchar
TestingTable ItemCode YES nvarchar
TestingTable ItemDesc YES nvarchar
TestingTable QuantityOrdered YES numeric
TestingTable ShipToLocation YES nvarchar
TestingTable DeliverToLocation YES nvarchar
TestingTable TraceNumber YES nvarchar
TestingTable BOL YES nvarchar
TestingTable PackSlipNumber YES nvarchar
TestingTable POTotalAmount YES numeric
TestingTable POLineAmount YES numeric
TestingTable CostCode YES nvarchar
TestingTable RequisitionId YES nvarchar
TestingTable RequisitionLineNumber YES int
TestingTable Vendor YES nvarchar
TestingTable ExchangeName YES nvarchar
TestingTable COECurrentProjectStatus YES nvarchar
TestingTable ReadyForService YES datetime
TestingTable MaterialSpecialist YES nvarchar
TestingTable QuantityReceived YES numeric
TestingTable DateReceived YES nvarchar
TestingTable ReceiverId YES nvarchar
TestingTable ScheduledShipDate YES datetime
TestingTable CalloutDetails YES nvarchar
TestingTable ProjectType YES nvarchar
TestingTable RecordStatus YES nvarchar
TestingTable MaterialComments YES nvarchar
TestingTable SchedulerComments YES nvarchar
TestingTable ID YES int
两列的ID是在添加行时创建的标识,并且不相互依赖。因此,尝试根据ID进行匹配不会起作用。我无法进行截断并从B重新填充,因为表中的人正在工作并锁定行。这就是为什么我只是更新,插入和删除行而不是整个表。我确实希望A完全是B,我不能截断和替换。
编辑4
这是我创建并运行的merge
脚本。它似乎有效,但它删除了每一行,然后插入每一行。我不知道这是应该发生的事情,还是我说错了?
begin tran --commit rollback
merge into pmdb.MaterialTracking as target
using (select State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,CalloutDetails,POStatus,BlanketRelease,PODateIssued,DateNeeded
,POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,QuantityReceived,DateReceived,RecordStatus,ShipToLocation,DeliverToLocation,ReceiverId
,TraceNumber,BOL,PackSlipNumber,POTotalAmount,POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,ProjectType
,COECurrentProjectStatus,ReadyForService,ScheduledShipDate,MaterialComments,SchedulerComments,MaterialSpecialist from working.MaterialTracking) as source
on (target.PONumber = source.PONumber and target.POLineNumber = source.POLineNumber and target.IMLineNumber = source.IMLineNumber
and target.ProjectNumber = source.ProjectNumber)
when matched and (ISNULL(Target.State,'NULL') <> ISNULL(Source.State,'NULL') OR
ISNULL(Target.SubProjectNumber,'NULL') <> ISNULL(Source.SubProjectNumber,'NULL') OR
ISNULL(Target.POStatus,'NULL') <> ISNULL(Source.POStatus,'NULL') OR
ISNULL(Target.BlanketRelease,'NULL') <> ISNULL(Source.BlanketRelease,'NULL') OR
ISNULL(Target.PODateIssued,'NULL') <> ISNULL(Source.PODateIssued,'NULL') OR
ISNULL(Target.DateNeeded,'NULL') <> ISNULL(Source.DateNeeded,'NULL') OR
ISNULL(Target.POInvoiceStatus,'NULL') <> ISNULL(Source.POInvoiceStatus,'NULL') OR
ISNULL(Target.ItemCode,'NULL') <> ISNULL(Source.ItemCode,'NULL') OR
ISNULL(Target.ItemDesc,'NULL') <> ISNULL(Source.ItemDesc,'NULL') OR
ISNULL(Target.QuantityOrdered,'NULL') <> ISNULL(Source.QuantityOrdered,'NULL') OR
ISNULL(Target.ShipToLocation,'NULL') <> ISNULL(Source.ShipToLocation,'NULL') OR
ISNULL(Target.DeliverToLocation,'NULL') <> ISNULL(Source.DeliverToLocation,'NULL') OR
ISNULL(Target.TraceNumber,'NULL') <> ISNULL(Source.TraceNumber,'NULL') OR
ISNULL(Target.BOL,'NULL') <> ISNULL(Source.BOL,'NULL') OR
ISNULL(Target.PackSlipNumber,'NULL') <> ISNULL(Source.PackSlipNumber,'NULL') OR
ISNULL(Target.POTotalAmount,'NULL') <> ISNULL(Source.POTotalAmount,'NULL') OR
ISNULL(Target.POLineAmount,'NULL') <> ISNULL(Source.POLineAmount,'NULL') OR
ISNULL(Target.CostCode,'NULL') <> ISNULL(Source.CostCode,'NULL') OR
ISNULL(Target.RequisitionId,'NULL') <> ISNULL(Source.RequisitionId,'NULL') OR
ISNULL(Target.RequisitionLineNumber,'NULL') <> ISNULL(Source.RequisitionLineNumber,'NULL') OR
ISNULL(Target.Vendor,'NULL') <> ISNULL(Source.Vendor,'NULL') OR
ISNULL(Target.ExchangeName,'NULL') <> ISNULL(Source.ExchangeName,'NULL') OR
ISNULL(Target.COECurrentProjectStatus,'NULL') <> ISNULL(Source.COECurrentProjectStatus,'NULL') OR
ISNULL(Target.ReadyForService,'NULL') <> ISNULL(Source.ReadyForService,'NULL') OR
ISNULL(Target.MaterialSpecialist,'NULL') <> ISNULL(Source.MaterialSpecialist,'NULL') OR
ISNULL(Target.QuantityReceived,'NULL') <> ISNULL(Source.QuantityReceived,'NULL') OR
ISNULL(Target.DateReceived,'NULL') <> ISNULL(Source.DateReceived,'NULL') OR
ISNULL(Target.ReceiverId,'NULL') <> ISNULL(Source.ReceiverId,'NULL') OR
ISNULL(Target.ScheduledShipDate,'NULL') <> ISNULL(Source.ScheduledShipDate,'NULL') OR
ISNULL(Target.CalloutDetails,'NULL') <> ISNULL(Source.CalloutDetails,'NULL') OR
ISNULL(Target.ProjectType,'NULL') <> ISNULL(Source.ProjectType,'NULL') OR
ISNULL(Target.RecordStatus,'NULL') <> ISNULL(Source.RecordStatus,'NULL') OR
ISNULL(Target.MaterialComments,'NULL') <> ISNULL(Source.MaterialComments,'NULL') OR
ISNULL(Target.SchedulerComments,'NULL') <> ISNULL(Source.SchedulerComments,'NULL'))
then update
set State = Source.State,
SubProjectNumber = Source.SubProjectNumber,
POStatus = Source.POStatus,
BlanketRelease = Source.BlanketRelease,
PODateIssued = Source.PODateIssued,
DateNeeded = Source.DateNeeded,
POInvoiceStatus = Source.POInvoiceStatus,
ItemCode = Source.ItemCode,
ItemDesc = Source.ItemDesc,
QuantityOrdered = Source.QuantityOrdered,
ShipToLocation = Source.ShipToLocation,
DeliverToLocation = Source.DeliverToLocation,
TraceNumber = Source.TraceNumber,
BOL = Source.BOL,
PackSlipNumber = Source.PackSlipNumber,
POTotalAmount = Source.POTotalAmount,
POLineAmount = Source.POLineAmount,
CostCode = Source.CostCode,
RequisitionId = Source.RequisitionId,
RequisitionLineNumber = Source.RequisitionLineNumber,
Vendor = Source.Vendor,
ExchangeName = Source.ExchangeName,
COECurrentProjectStatus = Source.COECurrentProjectStatus,
ReadyForService = Source.ReadyForService,
MaterialSpecialist = Source.MaterialSpecialist,
QuantityReceived = Source.QuantityReceived,
DateReceived = Source.DateReceived,
ReceiverId = Source.ReceiverId,
ScheduledShipDate = Source.ScheduledShipDate,
CalloutDetails = Source.CalloutDetails,
ProjectType = Source.ProjectType,
RecordStatus = Source.RecordStatus,
MaterialComments = Source.MaterialComments,
SchedulerComments = Source.SchedulerComments
when not matched by target then
insert (State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,CalloutDetails,POStatus,BlanketRelease,PODateIssued,DateNeeded
,POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,QuantityReceived,DateReceived,RecordStatus,ShipToLocation,DeliverToLocation,ReceiverId
,TraceNumber,BOL,PackSlipNumber,POTotalAmount,POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,ProjectType
,COECurrentProjectStatus,ReadyForService,ScheduledShipDate,MaterialComments,SchedulerComments,MaterialSpecialist)
values (State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,CalloutDetails,POStatus,BlanketRelease,PODateIssued,DateNeeded
,POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,QuantityReceived,DateReceived,RecordStatus,ShipToLocation,DeliverToLocation,ReceiverId
,TraceNumber,BOL,PackSlipNumber,POTotalAmount,POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,ProjectType
,COECurrentProjectStatus,ReadyForService,ScheduledShipDate,MaterialComments,SchedulerComments,MaterialSpecialist)
when not matched by source then
delete
output $action, Inserted.*,Deleted.*;
/*
select * from pmdb.MaterialTracking
*/
答案 0 :(得分:1)
这只是搞砸了
呃,那就是B
至于大多数列 - 定义最多 而现在A恰好是B所以无论如何这将是零
我的建议是有一个计划 3.最后一步是有缺陷的
您不需要计划100列
让我们假装4,前两个是比赛
并且所有都不是可空的
首先删除。较少的行是较少的行来比较。它可能会打开插入页面(减少页面拆分)。
delete b
from b
left join a
on a.col1 = b.col1
and a.col2 = b.col2
where a.col1 is null
接下来会变得有点棘手,因为合并你会更新,即使所有列都相同,并希望保持流量不受b
但如果大多数匹配将是更新,则使用合并
在插入之前进行更新,因为为什么处理的行数多于
update b
set b.col3 = a.col3, b.col4 = a.col4
from b
join a
on a.col1 = b.col1
and a.col2 = b.col2
and (a.col3 <> b.col3 or a.col4 <> b.col4)
现在插入
insert into b (col1, col2, col3, col3)
select col1, col2, col3, col3
from a
left join b
on a.col1 = b.col1
and a.col2 = b.col2
where b.col1 is null
答案 1 :(得分:1)
我仍然不会这样做,但每个人都在评论他们喜欢合并多少,所以这里是你的答案,这样你就可以做出自己的决定,因为没有人为你写作。< / p>
MERGE INTO TableA as target
USING (SELECT
ID
,Col1
,Col2
,Col3
FROM
TableB
) AS source
ON (t.ID = s.ID) --change to the relationship
WHEN MATCHED AND (target.Col1 <> source.Col1
OR target.Col2 <> source.Col2
OR ISNULL(target.Col3,'Null') <> ISNULL(source.Col3,'NULL'))
THEN
UPDATE
SET Col1 = source.Col1
,Col2 = source.Col2
WHEN NOT MATCHED BY TARGET THEN
--Insert Records That Do Not In Target Table
INSERT (Id,col1,col2,col3,...) --note this is the target table
VALUES (Id,col2,col2,col3) --ehese are source column names
WHEN NOT MATCHED BY SOURCE THEN
DELETE
--you could also choose to update a field in target as well
--Don't have to necessarily use output but statement must end with ;
OUTPUT $action, Inserted.*, Deleted.*;
请注意,您还可以为某些WHEN MATCHED或WHEN NOT MATCHED语句添加条件,以进一步限制您想要执行的操作。
这是
的一个例子WHEN NOT MATCHED BY TARGET AND source.col1 <> 'BAD' THEN
--Insert Records That Do Not In Target Table
INSERT (Id,col1,col2,col3,...)
VALUES (Id,col2,col2,col3)
再次比较你的行时,考虑如何处理空值的比较是很重要的。
查看您最近编辑的问题,我相信这两个答案明天都会改变。
答案 2 :(得分:1)
通常,我建议使用MERGE语句,因为它很容易设置,但由于缺少密钥,它在这里不能很好地工作。没有索引,这可能需要很长时间,但有38列,它也将是一个相当大的索引。不过,如果您遇到严重的性能问题,我建议您创建一个NONCLUSTERED索引。
您要做的是首先删除然后INSERT,在单个事务中执行,并在连接上处理NULL。通常,您首先执行DELETE,因为您不想遇到密钥违规。尝试在这里进行UPDATE没有任何意义。如果没有共享密钥,那么不可能告诉您何时更新,除非所有内容已经匹配时的简单案例。
如果您在MaterialTracking中有所有38个字段都有重复的记录,或者所有38个字段都为NULL,那么所有这些方法都会遇到问题。在这里没有共享密钥不是一个好主意。即使向TestTable添加一个字段来存储MaterialTracking中的主键也是可取的。
我会这样做:
BEGIN TRANSACTION;
;WITH TestTable_ToDelete AS (
SELECT tt.State,tt.ProjectNumber,tt.SubProjectNumber,tt.PONumber,tt.POLineNumber,tt.IMLineNumber,tt.POStatus,tt.BlanketRelease,tt.PODateIssued,tt.DateNeeded,
tt.POInvoiceStatus,tt.ItemCode,tt.ItemDesc,tt.QuantityOrdered,tt.ShipToLocation,tt.DeliverToLocation,tt.TraceNumber,tt.BOL,tt.PackSlipNumber,tt.POTotalAmount,
tt.POLineAmount,tt.CostCode,tt.RequisitionId,tt.RequisitionLineNumber,tt.Vendor,tt.ExchangeName,tt.COECurrentProjectStatus,tt.ReadyForService,tt.MaterialSpecialist,
tt.QuantityReceived,tt.DateReceived,tt.ReceiverId,tt.ScheduledShipDate,tt.CalloutDetails,tt.ProjectType,tt.RecordStatus,tt.MaterialComments,tt.SchedulerComments
FROM TestTable tt
EXCEPT
SELECT mt.State,mt.ProjectNumber,mt.SubProjectNumber,mt.PONumber,mt.POLineNumber,mt.IMLineNumber,mt.POStatus,mt.BlanketRelease,mt.PODateIssued,mt.DateNeeded,
mt.POInvoiceStatus,mt.ItemCode,mt.ItemDesc,mt.QuantityOrdered,mt.ShipToLocation,mt.DeliverToLocation,mt.TraceNumber,mt.BOL,mt.PackSlipNumber,mt.POTotalAmount,
mt.POLineAmount,mt.CostCode,mt.RequisitionId,mt.RequisitionLineNumber,mt.Vendor,mt.ExchangeName,mt.COECurrentProjectStatus,mt.ReadyForService,mt.MaterialSpecialist,
mt.QuantityReceived,mt.DateReceived,mt.ReceiverId,mt.ScheduledShipDate,mt.CalloutDetails,mt.ProjectType,mt.RecordStatus,mt.MaterialComments,mt.SchedulerComments
FROM MaterialTracking mt
)
DELETE FROM TestTable_ToDelete;
;WITH TestTable_ToInsert (
SELECT mt.State,mt.ProjectNumber,mt.SubProjectNumber,mt.PONumber,mt.POLineNumber,mt.IMLineNumber,mt.POStatus,mt.BlanketRelease,mt.PODateIssued,mt.DateNeeded,
mt.POInvoiceStatus,mt.ItemCode,mt.ItemDesc,mt.QuantityOrdered,mt.ShipToLocation,mt.DeliverToLocation,mt.TraceNumber,mt.BOL,mt.PackSlipNumber,mt.POTotalAmount,
mt.POLineAmount,mt.CostCode,mt.RequisitionId,mt.RequisitionLineNumber,mt.Vendor,mt.ExchangeName,mt.COECurrentProjectStatus,mt.ReadyForService,mt.MaterialSpecialist,
mt.QuantityReceived,mt.DateReceived,mt.ReceiverId,mt.ScheduledShipDate,mt.CalloutDetails,mt.ProjectType,mt.RecordStatus,mt.MaterialComments,mt.SchedulerComments
FROM MaterialTracking mt
EXCEPT
SELECT tt.State,tt.ProjectNumber,tt.SubProjectNumber,tt.PONumber,tt.POLineNumber,tt.IMLineNumber,tt.POStatus,tt.BlanketRelease,tt.PODateIssued,tt.DateNeeded,
tt.POInvoiceStatus,tt.ItemCode,tt.ItemDesc,tt.QuantityOrdered,tt.ShipToLocation,tt.DeliverToLocation,tt.TraceNumber,tt.BOL,tt.PackSlipNumber,tt.POTotalAmount,
tt.POLineAmount,tt.CostCode,tt.RequisitionId,tt.RequisitionLineNumber,tt.Vendor,tt.ExchangeName,tt.COECurrentProjectStatus,tt.ReadyForService,tt.MaterialSpecialist,
tt.QuantityReceived,tt.DateReceived,tt.ReceiverId,tt.ScheduledShipDate,tt.CalloutDetails,tt.ProjectType,tt.RecordStatus,tt.MaterialComments,tt.SchedulerComments
FROM TestTable tt
)
INSERT INTO TestTable (State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,POStatus,BlanketRelease,PODateIssued,DateNeeded,
POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,ShipToLocation,DeliverToLocation,TraceNumber,BOL,PackSlipNumber,POTotalAmount,
POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,COECurrentProjectStatus,ReadyForService,MaterialSpecialist,
QuantityReceived,DateReceived,ReceiverId,ScheduledShipDate,CalloutDetails,ProjectType,RecordStatus,MaterialComments,SchedulerComments)
SELECT State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,POStatus,BlanketRelease,PODateIssued,DateNeeded,
POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,ShipToLocation,DeliverToLocation,TraceNumber,BOL,PackSlipNumber,POTotalAmount,
POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,COECurrentProjectStatus,ReadyForService,MaterialSpecialist,
QuantityReceived,DateReceived,ReceiverId,ScheduledShipDate,CalloutDetails,ProjectType,RecordStatus,MaterialComments,SchedulerComments
FROM TestTable_ToInsert;
COMMIT TRANSACTION;
替代方案是做这样的事情,但它可能会一样慢。注意JOIN条件有多大,因为字段可以为空。除非你有钥匙,否则没有办法解决这个问题。
BEGIN TRANSACTION MAIN;
DELETE tt
FROM TestingTable tt
LEFT JOIN MaterialTracking mt
ON (mt.State = tt.State OR (mt.State IS NULL AND tt.State IS NULL))
AND (mt.ProjectNumber = tt.ProjectNumber OR (mt.ProjectNumber IS NULL AND tt.ProjectNumber IS NULL))
AND (mt.SubProjectNumber = tt.SubProjectNumber OR (mt.SubProjectNumber IS NULL AND tt.SubProjectNumber IS NULL))
AND (mt.PONumber = tt.PONumber OR (mt.PONumber IS NULL AND tt.PONumber IS NULL))
AND (mt.POLineNumber = tt.POLineNumber OR (mt.POLineNumber IS NULL AND tt.POLineNumber IS NULL))
AND (mt.IMLineNumber = tt.IMLineNumber OR (mt.IMLineNumber IS NULL AND tt.IMLineNumber IS NULL))
AND (mt.POStatus = tt.POStatus OR (mt.POStatus IS NULL AND tt.POStatus IS NULL))
AND (mt.BlanketRelease = tt.BlanketRelease OR (mt.BlanketRelease IS NULL AND tt.BlanketRelease IS NULL))
AND (mt.PODateIssued = tt.PODateIssued OR (mt.PODateIssued IS NULL AND tt.PODateIssued IS NULL))
AND (mt.DateNeeded = tt.DateNeeded OR (mt.DateNeeded IS NULL AND tt.DateNeeded IS NULL))
AND (mt.POInvoiceStatus = tt.POInvoiceStatus OR (mt.POInvoiceStatus IS NULL AND tt.POInvoiceStatus IS NULL))
AND (mt.ItemCode = tt.ItemCode OR (mt.ItemCode IS NULL AND tt.ItemCode IS NULL))
AND (mt.ItemDesc = tt.ItemDesc OR (mt.ItemDesc IS NULL AND tt.ItemDesc IS NULL))
AND (mt.QuantityOrdered = tt.QuantityOrdered OR (mt.QuantityOrdered IS NULL AND tt.QuantityOrdered IS NULL))
AND (mt.ShipToLocation = tt.ShipToLocation OR (mt.ShipToLocation IS NULL AND tt.ShipToLocation IS NULL))
AND (mt.DeliverToLocation = tt.DeliverToLocation OR (mt.DeliverToLocation IS NULL AND tt.DeliverToLocation IS NULL))
AND (mt.TraceNumber = tt.TraceNumber OR (mt.TraceNumber IS NULL AND tt.TraceNumber IS NULL))
AND (mt.BOL = tt.BOL OR (mt.BOL IS NULL AND tt.BOL IS NULL))
AND (mt.PackSlipNumber = tt.PackSlipNumber OR (mt.PackSlipNumber IS NULL AND tt.PackSlipNumber IS NULL))
AND (mt.POTotalAmount = tt.POTotalAmount OR (mt.POTotalAmount IS NULL AND tt.POTotalAmount IS NULL))
AND (mt.POLineAmount = tt.POLineAmount OR (mt.POLineAmount IS NULL AND tt.POLineAmount IS NULL))
AND (mt.CostCode = tt.CostCode OR (mt.CostCode IS NULL AND tt.CostCode IS NULL))
AND (mt.RequisitionId = tt.RequisitionId OR (mt.RequisitionId IS NULL AND tt.RequisitionId IS NULL))
AND (mt.RequisitionLineNumber = tt.RequisitionLineNumber OR (mt.RequisitionLineNumber IS NULL AND tt.RequisitionLineNumber IS NULL))
AND (mt.Vendor = tt.Vendor OR (mt.Vendor IS NULL AND tt.Vendor IS NULL))
AND (mt.ExchangeName = tt.ExchangeName OR (mt.ExchangeName IS NULL AND tt.ExchangeName IS NULL))
AND (mt.COECurrentProjectStatus = tt.COECurrentProjectStatus OR (mt.COECurrentProjectStatus IS NULL AND tt.COECurrentProjectStatus IS NULL))
AND (mt.ReadyForService = tt.ReadyForService OR (mt.ReadyForService IS NULL AND tt.ReadyForService IS NULL))
AND (mt.MaterialSpecialist = tt.MaterialSpecialist OR (mt.MaterialSpecialist IS NULL AND tt.MaterialSpecialist IS NULL))
AND (mt.QuantityReceived = tt.QuantityReceived OR (mt.QuantityReceived IS NULL AND tt.QuantityReceived IS NULL))
AND (mt.DateReceived = tt.DateReceived OR (mt.DateReceived IS NULL AND tt.DateReceived IS NULL))
AND (mt.ReceiverId = tt.ReceiverId OR (mt.ReceiverId IS NULL AND tt.ReceiverId IS NULL))
AND (mt.ScheduledShipDate = tt.ScheduledShipDate OR (mt.ScheduledShipDate IS NULL AND tt.ScheduledShipDate IS NULL))
AND (mt.CalloutDetails = tt.CalloutDetails OR (mt.CalloutDetails IS NULL AND tt.CalloutDetails IS NULL))
AND (mt.ProjectType = tt.ProjectType OR (mt.ProjectType IS NULL AND tt.ProjectType IS NULL))
AND (mt.RecordStatus = tt.RecordStatus OR (mt.RecordStatus IS NULL AND tt.RecordStatus IS NULL))
AND (mt.MaterialComments = tt.MaterialComments OR (mt.MaterialComments IS NULL AND tt.MaterialComments IS NULL))
AND (mt.SchedulerComments = tt.SchedulerComments OR (mt.SchedulerComments IS NULL AND tt.SchedulerComments IS NULL))
WHERE mt.State IS NULL
AND mt.ProjectNumber IS NULL
AND mt.SubProjectNumber IS NULL
AND mt.PONumber IS NULL
AND mt.POLineNumber IS NULL
AND mt.IMLineNumber IS NULL
AND mt.POStatus IS NULL
AND mt.BlanketRelease IS NULL
AND mt.PODateIssued IS NULL
AND mt.DateNeeded IS NULL
AND mt.POInvoiceStatus IS NULL
AND mt.ItemCode IS NULL
AND mt.ItemDesc IS NULL
AND mt.QuantityOrdered IS NULL
AND mt.ShipToLocation IS NULL
AND mt.DeliverToLocation IS NULL
AND mt.TraceNumber IS NULL
AND mt.BOL IS NULL
AND mt.PackSlipNumber IS NULL
AND mt.POTotalAmount IS NULL
AND mt.POLineAmount IS NULL
AND mt.CostCode IS NULL
AND mt.RequisitionId IS NULL
AND mt.RequisitionLineNumber IS NULL
AND mt.Vendor IS NULL
AND mt.ExchangeName IS NULL
AND mt.COECurrentProjectStatus IS NULL
AND mt.ReadyForService IS NULL
AND mt.MaterialSpecialist IS NULL
AND mt.QuantityReceived IS NULL
AND mt.DateReceived IS NULL
AND mt.ReceiverId IS NULL
AND mt.ScheduledShipDate IS NULL
AND mt.CalloutDetails IS NULL
AND mt.ProjectType IS NULL
AND mt.RecordStatus IS NULL
AND mt.MaterialComments IS NULL
AND mt.SchedulerComments IS NULL;
INSERT INTO TestTable (State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,POStatus,BlanketRelease,PODateIssued,DateNeeded,
POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,ShipToLocation,DeliverToLocation,TraceNumber,BOL,PackSlipNumber,POTotalAmount,
POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,COECurrentProjectStatus,ReadyForService,MaterialSpecialist,
QuantityReceived,DateReceived,ReceiverId,ScheduledShipDate,CalloutDetails,ProjectType,RecordStatus,MaterialComments,SchedulerComments)
SELECT mt.State,mt.ProjectNumber,mt.SubProjectNumber,mt.PONumber,mt.POLineNumber,mt.IMLineNumber,mt.POStatus,mt.BlanketRelease,mt.PODateIssued,mt.DateNeeded,
mt.POInvoiceStatus,mt.ItemCode,mt.ItemDesc,mt.QuantityOrdered,mt.ShipToLocation,mt.DeliverToLocation,mt.TraceNumber,mt.BOL,mt.PackSlipNumber,mt.POTotalAmount,
mt.POLineAmount,mt.CostCode,mt.RequisitionId,mt.RequisitionLineNumber,mt.Vendor,mt.ExchangeName,mt.COECurrentProjectStatus,mt.ReadyForService,mt.MaterialSpecialist,
mt.QuantityReceived,mt.DateReceived,mt.ReceiverId,mt.ScheduledShipDate,mt.CalloutDetails,mt.ProjectType,mt.RecordStatus,mt.MaterialComments,mt.SchedulerComments
FROM TestingTable tt
RIGHT JOIN MaterialTracking mt
ON (mt.State = tt.State OR (mt.State IS NULL AND tt.State IS NULL))
AND (mt.ProjectNumber = tt.ProjectNumber OR (mt.ProjectNumber IS NULL AND tt.ProjectNumber IS NULL))
AND (mt.SubProjectNumber = tt.SubProjectNumber OR (mt.SubProjectNumber IS NULL AND tt.SubProjectNumber IS NULL))
AND (mt.PONumber = tt.PONumber OR (mt.PONumber IS NULL AND tt.PONumber IS NULL))
AND (mt.POLineNumber = tt.POLineNumber OR (mt.POLineNumber IS NULL AND tt.POLineNumber IS NULL))
AND (mt.IMLineNumber = tt.IMLineNumber OR (mt.IMLineNumber IS NULL AND tt.IMLineNumber IS NULL))
AND (mt.POStatus = tt.POStatus OR (mt.POStatus IS NULL AND tt.POStatus IS NULL))
AND (mt.BlanketRelease = tt.BlanketRelease OR (mt.BlanketRelease IS NULL AND tt.BlanketRelease IS NULL))
AND (mt.PODateIssued = tt.PODateIssued OR (mt.PODateIssued IS NULL AND tt.PODateIssued IS NULL))
AND (mt.DateNeeded = tt.DateNeeded OR (mt.DateNeeded IS NULL AND tt.DateNeeded IS NULL))
AND (mt.POInvoiceStatus = tt.POInvoiceStatus OR (mt.POInvoiceStatus IS NULL AND tt.POInvoiceStatus IS NULL))
AND (mt.ItemCode = tt.ItemCode OR (mt.ItemCode IS NULL AND tt.ItemCode IS NULL))
AND (mt.ItemDesc = tt.ItemDesc OR (mt.ItemDesc IS NULL AND tt.ItemDesc IS NULL))
AND (mt.QuantityOrdered = tt.QuantityOrdered OR (mt.QuantityOrdered IS NULL AND tt.QuantityOrdered IS NULL))
AND (mt.ShipToLocation = tt.ShipToLocation OR (mt.ShipToLocation IS NULL AND tt.ShipToLocation IS NULL))
AND (mt.DeliverToLocation = tt.DeliverToLocation OR (mt.DeliverToLocation IS NULL AND tt.DeliverToLocation IS NULL))
AND (mt.TraceNumber = tt.TraceNumber OR (mt.TraceNumber IS NULL AND tt.TraceNumber IS NULL))
AND (mt.BOL = tt.BOL OR (mt.BOL IS NULL AND tt.BOL IS NULL))
AND (mt.PackSlipNumber = tt.PackSlipNumber OR (mt.PackSlipNumber IS NULL AND tt.PackSlipNumber IS NULL))
AND (mt.POTotalAmount = tt.POTotalAmount OR (mt.POTotalAmount IS NULL AND tt.POTotalAmount IS NULL))
AND (mt.POLineAmount = tt.POLineAmount OR (mt.POLineAmount IS NULL AND tt.POLineAmount IS NULL))
AND (mt.CostCode = tt.CostCode OR (mt.CostCode IS NULL AND tt.CostCode IS NULL))
AND (mt.RequisitionId = tt.RequisitionId OR (mt.RequisitionId IS NULL AND tt.RequisitionId IS NULL))
AND (mt.RequisitionLineNumber = tt.RequisitionLineNumber OR (mt.RequisitionLineNumber IS NULL AND tt.RequisitionLineNumber IS NULL))
AND (mt.Vendor = tt.Vendor OR (mt.Vendor IS NULL AND tt.Vendor IS NULL))
AND (mt.ExchangeName = tt.ExchangeName OR (mt.ExchangeName IS NULL AND tt.ExchangeName IS NULL))
AND (mt.COECurrentProjectStatus = tt.COECurrentProjectStatus OR (mt.COECurrentProjectStatus IS NULL AND tt.COECurrentProjectStatus IS NULL))
AND (mt.ReadyForService = tt.ReadyForService OR (mt.ReadyForService IS NULL AND tt.ReadyForService IS NULL))
AND (mt.MaterialSpecialist = tt.MaterialSpecialist OR (mt.MaterialSpecialist IS NULL AND tt.MaterialSpecialist IS NULL))
AND (mt.QuantityReceived = tt.QuantityReceived OR (mt.QuantityReceived IS NULL AND tt.QuantityReceived IS NULL))
AND (mt.DateReceived = tt.DateReceived OR (mt.DateReceived IS NULL AND tt.DateReceived IS NULL))
AND (mt.ReceiverId = tt.ReceiverId OR (mt.ReceiverId IS NULL AND tt.ReceiverId IS NULL))
AND (mt.ScheduledShipDate = tt.ScheduledShipDate OR (mt.ScheduledShipDate IS NULL AND tt.ScheduledShipDate IS NULL))
AND (mt.CalloutDetails = tt.CalloutDetails OR (mt.CalloutDetails IS NULL AND tt.CalloutDetails IS NULL))
AND (mt.ProjectType = tt.ProjectType OR (mt.ProjectType IS NULL AND tt.ProjectType IS NULL))
AND (mt.RecordStatus = tt.RecordStatus OR (mt.RecordStatus IS NULL AND tt.RecordStatus IS NULL))
AND (mt.MaterialComments = tt.MaterialComments OR (mt.MaterialComments IS NULL AND tt.MaterialComments IS NULL))
AND (mt.SchedulerComments = tt.SchedulerComments OR (mt.SchedulerComments IS NULL AND tt.SchedulerComments IS NULL))
WHERE tt.State IS NULL
AND tt.ProjectNumber IS NULL
AND tt.SubProjectNumber IS NULL
AND tt.PONumber IS NULL
AND tt.POLineNumber IS NULL
AND tt.IMLineNumber IS NULL
AND tt.POStatus IS NULL
AND tt.BlanketRelease IS NULL
AND tt.PODateIssued IS NULL
AND tt.DateNeeded IS NULL
AND tt.POInvoiceStatus IS NULL
AND tt.ItemCode IS NULL
AND tt.ItemDesc IS NULL
AND tt.QuantityOrdered IS NULL
AND tt.ShipToLocation IS NULL
AND tt.DeliverToLocation IS NULL
AND tt.TraceNumber IS NULL
AND tt.BOL IS NULL
AND tt.PackSlipNumber IS NULL
AND tt.POTotalAmount IS NULL
AND tt.POLineAmount IS NULL
AND tt.CostCode IS NULL
AND tt.RequisitionId IS NULL
AND tt.RequisitionLineNumber IS NULL
AND tt.Vendor IS NULL
AND tt.ExchangeName IS NULL
AND tt.COECurrentProjectStatus IS NULL
AND tt.ReadyForService IS NULL
AND tt.MaterialSpecialist IS NULL
AND tt.QuantityReceived IS NULL
AND tt.DateReceived IS NULL
AND tt.ReceiverId IS NULL
AND tt.ScheduledShipDate IS NULL
AND tt.CalloutDetails IS NULL
AND tt.ProjectType IS NULL
AND tt.RecordStatus IS NULL
AND tt.MaterialComments IS NULL
AND tt.SchedulerComments IS NULL;
COMMIT TRANSACTION MAIN;
请注意,如果您有一个合法记录,其中所有38个字段都为NULL,则将删除,并且不将使用此方法复制。
如果要尝试MERGE,可以使用上一个语句中的JOIN逻辑。 HOLDLOCK
锁定提示非常重要,因为它可以缓解人们在语句中遇到的几乎所有常见问题(如果通常是正确的话)。
MEREGE INTO TestTable WITH (HOLDLOCK) AS target
USING MaterialTracking AS source
ON (source.State = target.State OR (source.State IS NULL AND target.State IS NULL))
AND (source.ProjectNumber = target.ProjectNumber OR (source.ProjectNumber IS NULL AND target.ProjectNumber IS NULL))
AND (source.SubProjectNumber = target.SubProjectNumber OR (source.SubProjectNumber IS NULL AND target.SubProjectNumber IS NULL))
AND (source.PONumber = target.PONumber OR (source.PONumber IS NULL AND target.PONumber IS NULL))
AND (source.POLineNumber = target.POLineNumber OR (source.POLineNumber IS NULL AND target.POLineNumber IS NULL))
AND (source.IMLineNumber = target.IMLineNumber OR (source.IMLineNumber IS NULL AND target.IMLineNumber IS NULL))
AND (source.POStatus = target.POStatus OR (source.POStatus IS NULL AND target.POStatus IS NULL))
AND (source.BlanketRelease = target.BlanketRelease OR (source.BlanketRelease IS NULL AND target.BlanketRelease IS NULL))
AND (source.PODateIssued = target.PODateIssued OR (source.PODateIssued IS NULL AND target.PODateIssued IS NULL))
AND (source.DateNeeded = target.DateNeeded OR (source.DateNeeded IS NULL AND target.DateNeeded IS NULL))
AND (source.POInvoiceStatus = target.POInvoiceStatus OR (source.POInvoiceStatus IS NULL AND target.POInvoiceStatus IS NULL))
AND (source.ItemCode = target.ItemCode OR (source.ItemCode IS NULL AND target.ItemCode IS NULL))
AND (source.ItemDesc = target.ItemDesc OR (source.ItemDesc IS NULL AND target.ItemDesc IS NULL))
AND (source.QuantityOrdered = target.QuantityOrdered OR (source.QuantityOrdered IS NULL AND target.QuantityOrdered IS NULL))
AND (source.ShipToLocation = target.ShipToLocation OR (source.ShipToLocation IS NULL AND target.ShipToLocation IS NULL))
AND (source.DeliverToLocation = target.DeliverToLocation OR (source.DeliverToLocation IS NULL AND target.DeliverToLocation IS NULL))
AND (source.TraceNumber = target.TraceNumber OR (source.TraceNumber IS NULL AND target.TraceNumber IS NULL))
AND (source.BOL = target.BOL OR (source.BOL IS NULL AND target.BOL IS NULL))
AND (source.PackSlipNumber = target.PackSlipNumber OR (source.PackSlipNumber IS NULL AND target.PackSlipNumber IS NULL))
AND (source.POTotalAmount = target.POTotalAmount OR (source.POTotalAmount IS NULL AND target.POTotalAmount IS NULL))
AND (source.POLineAmount = target.POLineAmount OR (source.POLineAmount IS NULL AND target.POLineAmount IS NULL))
AND (source.CostCode = target.CostCode OR (source.CostCode IS NULL AND target.CostCode IS NULL))
AND (source.RequisitionId = target.RequisitionId OR (source.RequisitionId IS NULL AND target.RequisitionId IS NULL))
AND (source.RequisitionLineNumber = target.RequisitionLineNumber OR (source.RequisitionLineNumber IS NULL AND target.RequisitionLineNumber IS NULL))
AND (source.Vendor = target.Vendor OR (source.Vendor IS NULL AND target.Vendor IS NULL))
AND (source.ExchangeName = target.ExchangeName OR (source.ExchangeName IS NULL AND target.ExchangeName IS NULL))
AND (source.COECurrentProjectStatus = target.COECurrentProjectStatus OR (source.COECurrentProjectStatus IS NULL AND target.COECurrentProjectStatus IS NULL))
AND (source.ReadyForService = target.ReadyForService OR (source.ReadyForService IS NULL AND target.ReadyForService IS NULL))
AND (source.MaterialSpecialist = target.MaterialSpecialist OR (source.MaterialSpecialist IS NULL AND target.MaterialSpecialist IS NULL))
AND (source.QuantityReceived = target.QuantityReceived OR (source.QuantityReceived IS NULL AND target.QuantityReceived IS NULL))
AND (source.DateReceived = target.DateReceived OR (source.DateReceived IS NULL AND target.DateReceived IS NULL))
AND (source.ReceiverId = target.ReceiverId OR (source.ReceiverId IS NULL AND target.ReceiverId IS NULL))
AND (source.ScheduledShipDate = target.ScheduledShipDate OR (source.ScheduledShipDate IS NULL AND target.ScheduledShipDate IS NULL))
AND (source.CalloutDetails = target.CalloutDetails OR (source.CalloutDetails IS NULL AND target.CalloutDetails IS NULL))
AND (source.ProjectType = target.ProjectType OR (source.ProjectType IS NULL AND target.ProjectType IS NULL))
AND (source.RecordStatus = target.RecordStatus OR (source.RecordStatus IS NULL AND target.RecordStatus IS NULL))
AND (source.MaterialComments = target.MaterialComments OR (source.MaterialComments IS NULL AND target.MaterialComments IS NULL))
AND (source.SchedulerComments = target.SchedulerComments OR (source.SchedulerComments IS NULL AND target.SchedulerComments IS NULL))
WHEN NOT MATCHED BY TARGET THEN
INSERT (State,ProjectNumber,SubProjectNumber,PONumber,POLineNumber,IMLineNumber,POStatus,BlanketRelease,PODateIssued,DateNeeded,
POInvoiceStatus,ItemCode,ItemDesc,QuantityOrdered,ShipToLocation,DeliverToLocation,TraceNumber,BOL,PackSlipNumber,POTotalAmount,
POLineAmount,CostCode,RequisitionId,RequisitionLineNumber,Vendor,ExchangeName,COECurrentProjectStatus,ReadyForService,MaterialSpecialist,
QuantityReceived,DateReceived,ReceiverId,ScheduledShipDate,CalloutDetails,ProjectType,RecordStatus,MaterialComments,SchedulerComments)
VALUES (source.State,source.ProjectNumber,source.SubProjectNumber,source.PONumber,source.POLineNumber,source.IMLineNumber,source.POStatus,source.BlanketRelease,
source.PODateIssued,source.DateNeeded,source.POInvoiceStatus,source.ItemCode,source.ItemDesc,source.QuantityOrdered,source.ShipToLocation,
source.DeliverToLocation,source.TraceNumber,source.BOL,source.PackSlipNumber,source.POTotalAmount,source.POLineAmount,source.CostCode,
source.RequisitionId,source.RequisitionLineNumber,source.Vendor,source.ExchangeName,source.COECurrentProjectStatus,source.ReadyForService,
source.MaterialSpecialist,source.QuantityReceived,source.DateReceived,source.ReceiverId,source.ScheduledShipDate,source.CalloutDetails,
source.ProjectType,source.RecordStatus,source.MaterialComments,source.SchedulerComments)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
这应该有效,但我不是因为我已经提到的原因而不是它的忠实粉丝。同样,如果您有重复项或有效记录都是NULL值,您可能会遇到问题。
此外,由于有人试图编辑我的答案,我不是ISNULL(Target.SubProjectNumber,'NULL') = ISNULL(Source.SubProjectNumber,'NULL')
之类的逻辑粉丝。首先,它是因为它为您加入或比较的每个字段执行两个函数。这意味着会有一些额外的开销,但更糟糕的是,你删除了数据库引擎使用索引的能力。还有一个问题是,对于您决定合并/无效的任何值,您可能具有合法值。从长远来看,使用(source.SubProjectNumber = target.SubProjectNumber OR (source.SubProjectNumber IS NULL AND target.SubProjectNumber IS NULL))
要好得多。如果你有一个支持列模式的漂亮的文本编辑器,那真的不难。
答案 3 :(得分:0)
不是比较某些巨型where子句中的每一列,而是创建我称之为&#34;虚拟键&#34;这将使数据比较容易。实际上,您可以创建2个键,一个用于&#34;所有列&#34;和#34;大多数列&#34;根据您的要求。
要做到这一点(这是一个非常简单的例子,可能不适合制作):
select
a.field1,
a.field2, --etc.
hashbytes('sha2_256', concat(a.field1, '|', a.field2)) as most_col_hash,
hashbytes('sha2_256', concat(a.field1, '|', a.field2, '|', a.field3)) /*...etc. */ as all_col_hash
into #a_hashed
from table_a
等
现在,您可以在两个临时表中使用all_col_hash来确定哪些行有任何差异,并且您可以使用some_col_hash来确定哪些行与您用于生成哈希的列不同。
您希望在脚本开头检查临时表是否存在(如果存在则删除)。
您还应该使用create table语句而不是select into,我只是想在这里显示hashbytes的用法。
此外,我认为您应该使用某种身份字段或主键。
编辑:一些警告 - 输入字符串的限制是8000字节。此外,哈希是典型的情感。如果您希望不区分大小写,则必须对输入进行规范化,否则最终会得到技术上等效的行(如果排序规则不区分大小写)但是具有不同的哈希值。
答案 4 :(得分:-3)
似乎我的“不要用户MERGE
”声明不受欢迎。我支持我的陈述我已经通过删除它看到了我自己的ETL的改进。它基本上与下面的内容相同。我还发现当处理十几个行时,它们会独立地对每个语句进行故障排除,从而比通过合并更有效。
首先使用3条语句更新记录。
因此,查找两个表中但不同的记录。确保在比较时处理字段中的NULL
值,因为并非每种数据类型都能很好地将null与null进行比较。
UPDATE A
SET Col1 = b.Col1
,Col2 = b.Col2
,Col3 = c.Col3
...
FROM
TableA a
INNER JOIN TableB b
ON a.PrimaryKey = b.PrimaryKey -- or whatever the relatnioship is
WHERE
a.Col1 <> b.Col1
OR a.Col2 <> b.Col2
OR ISNULL(a.Col3,'DefaultValue') <> ISNULL(b.Col3,'DefaultValue')
OR ...
然后找到A
和B
中不在insert
的记录
INSERT INTO TableA (Col1,Col2,Col3,...)
SELECT
Col1
,Col2
,Col3
,...
FROM
TableB b
LEFT JOIN TableA a
ON b.PrimaryKey = a.PrimaryKey
WHERE
a.PrimaryKey IS NULL
然后delete
a
中不在b
DELETE a
FROM
TableA a
LEFT JOIN TableB b
ON a.PrimaryKey = b.PrimaryKey
WHERE
b.PrimaryKey IS NULL
的记录
join
请务必确保{{1}}的关系部分具有正确的列
有关为何不使用合并的更多信息,请在此处进行互联网搜索,这是mssqltips.com上所有错误的一篇文章:https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/
有趣的是,这会得到一个低票,因为它不受欢迎,但它是有效的,在一些数据库平台上你唯一的选择。这是几十年来合并记录的主要方法之一。