比较两个SQL表并找出差异

时间:2016-06-20 19:33:35

标签: sql sql-server

我有两个表,每个表有30多列。我需要比较表并找到那些

的行
  1. 在一个表中,但在另一个表中
  2. 大多数列都相同,但不是全部
  3. 我很难完成这项工作。我尝试过使用Union All来比较两张桌子。使用表A和B,我得到

    的所有行
    1. 在A中,而不在B
    2. 在B中而不在A
    3. 在两个表格中,但不是所有列都完全相同
    4. 我已经使用了SQL的except函数,我可以从A中获取不在B中的所有行或从B中不在A中的所有行。

      我有一个根据this博客文章执行UNION ALL的SP。然后,我发现Except用于获取两个表的差异并尝试过。然而,我无法实现我的目标。我最终要做的是我在A中的数据需要根据表B中的内容进行更新/删除/添加。我希望能够比较2表和

      1. 从B中插入尚未包含在A
      2. 中的内容
      3. 从A中删除不存在的内容
      4. 更新A,其中B中的行仅与几列中的A不同
      5. 任何帮助或建议都将不胜感激。

        编辑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
        */
        

5 个答案:

答案 0 :(得分:1)

这只是搞砸了

  1. 从B中插入尚未包含在A
  2. 中的内容
  3. 从A中删除不存在的内容
  4. 呃,那就是B

    1. 更新A,B中的行与A中的行不同 列
    2. 至于大多数列 - 定义最多 而现在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 ...

然后找到AB中不在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/

有趣的是,这会得到一个低票,因为它不受欢迎,但它是有效的,在一些数据库平台上你唯一的选择。这是几十年来合并记录的主要方法之一。