简体   繁体   English

在 MERGE SQL 查询中遇到问题

[英]Facing an issue in MERGE SQL query

I have a requirement, insert/update data from staging table stgTbl to another table T2.我有一个要求,将数据从暂存表 stgTbl 插入/更新到另一个表 T2。 If exists update, no matter how many duplicates are there.如果存在更新,无论有多少重复项。 Similarly, if not exists insert directly T2.同样,如果不存在,直接插入T2。 Very Simple.很简单的。 Since the staging table stgTb1 is scheduled job everyday.由于暂存表 stgTb1 是每天的预定作业。 Sometime I would get multiple duplicate rows as well.有时我也会得到多个重复的行。 So because of duplicates, merge statement producing an error:因此,由于重复,合并语句产生错误:

"The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row". “MERGE 语句试图多次更新或删除同一行。当目标行匹配多个源行时会发生这种情况”。

I tried with checksum but still getting because i may done wrongly in checksum.我尝试使用校验和但仍然得到,因为我可能在校验和中做错了。 There is no primary key in both the tables (i removed, because otherwise i am getting primary key constraint error).两个表中都没有主键(我删除了,否则我会收到主键约束错误)。 Based on columns (account and ref_key2) should go with insert/update.基于列(帐户和 ref_key2)应该 go 插入/更新。 I have tried with if else with exists also but somehow this is also not working if in case there are 0 records in the target table T2.我已经尝试过 if else with exists also 但不知何故如果目标表 T2 中有 0 条记录,这也不起作用。 SQL masters could solve this issue. SQL高手可以解决这个问题。 Appreciate their knowledge share.感谢他们的知识共享。

CREATE OR ALTER Trigger [dbo].[tr_Merge_Personal_Expense] on [dbo]. 
[Personal_Expense_Staging]
AFTER INSERT
AS

BEGIN

DECLARE @SummaryOfChanges TABLE(Change nvarchar(20));

         MERGE [dbo].[Personal_Expense] AS TARGET 
         USING (
         SELECT *,
                CHECKSUM(
                             ISNULL(CONVERT(nvarchar (3) ,[Client]),'0'),
                             ISNULL(CONVERT(nvarchar (50),[Text]),'0'),
                             ISNULL(CONVERT(nvarchar (10),[Cost_Center]),'0'),
                             ISNULL(CONVERT(nvarchar (2) ,[Posting_Period]),'0'),
                             ISNULL(CONVERT(nvarchar (10),[Profit]),'0') ,
                             ISNULL(CONVERT(nvarchar (2) ,[Document_Type]),'0'),
                             ISNULL(CONVERT(nvarchar (4) ,[Company_Code]),'0') ,
                             -- ISNULL(CONVERT(nvarchar (10),[Account]),'0'),
                             ISNULL(CONVERT(nvarchar (20),[Amount_In_Doc_Curr]),'0'),
                             ISNULL(CONVERT(nvarchar (5) ,[Document_Currency]),'0') ,
                             ISNULL(CONVERT(nvarchar (20),[Amount_In_local_Curr]),'0') ,
                             ISNULL(CONVERT(nvarchar (20),[Amount_In_Grp_Curr]),'0'),
                             ISNULL(CONVERT(nvarchar (25),[Group]),'0'),
                             [Posting_Date],
                             ISNULL(CONVERT(nvarchar (18), [Assignment]),'0'),
                             ISNULL(CONVERT(nvarchar (16), [Reference]),'0'),
                             ISNULL(CONVERT(nvarchar (20), [Reference_Key1]),'0') ,
                             --[Reference_Key2] [nvarchar](12) NOT NULL,
                             ISNULL(CONVERT(nvarchar (20), [Reference_Key3]),'0') ,
                             ISNULL(CONVERT(nvarchar (20), [Document_Number]),'0') ,
                             ISNULL(CONVERT(nvarchar (25), [Document_Header_Text]),'0') 
                 ) AS [HashChecksum]
         FROM
         [dbo].[Personal_Expense_Staging]
         ) AS SOURCE 
         ON (
                TARGET.[Reference_Key2] = SOURCE.[Reference_Key2] AND
                TARGET.[Account] = SOURCE.[Account] 
            )

         -----   Update 
         WHEN MATCHED AND ( TARGET.[HashChecksum] <> SOURCE.[HashChecksum] ) 
         THEN
         UPDATE SET  
                TARGET.[client] = SOURCE.[client],
                TARGET.[text] = SOURCE.[text],
                TARGET.[cost_center] = SOURCE.[cost_center],
                TARGET.[posting_period] = SOURCE.[posting_period],
                TARGET.[profit] = SOURCE.[profit],
                TARGET.[document_type]= SOURCE.[document_type],
                TARGET.[company_code] = SOURCE.[company_code],
                TARGET.[Account] = SOURCE.[Account],
                TARGET.[Amount_In_Doc_Curr] = SOURCE.[Amount_In_Doc_Curr],
                TARGET.[document_currency] = SOURCE.[document_currency],
                TARGET.[Amount_In_local_Curr] = SOURCE.[Amount_In_local_Curr],
                TARGET.[Amount_In_Grp_Curr] = SOURCE.[Amount_In_Grp_Curr],
                TARGET.[group] = SOURCE.[group],
                TARGET.[posting_date] = SOURCE.[posting_date],
                TARGET.[assignment] = SOURCE.[assignment],
                TARGET.[reference] = SOURCE.[reference],
                TARGET.[document_header_text] = SOURCE.[document_header_text],
                TARGET.[Last_updated_DateTime] = GETDATE(),
                TARGET.[HashChecksum] =  SOURCE.[HashChecksum]

         -- Insert 

         WHEN NOT MATCHED THEN
         INSERT ( 
                       [Client],
                       [text],
                       [cost_center],
                       [posting_period],
                       [profit],
                       [document_type],
                       [company_code],
                       [Account],
                       [Amount_In_Doc_Curr],
                       [document_currency],
                       [Amount_In_local_Curr],
                       [Amount_In_Grp_Curr],
                       [group],
                       [posting_date],
                       [assignment],
                       [reference],
                       [reference_key2],
                       [reference_key3],
                       [document_number],
                       [document_header_text],
                       [Last_updated_DateTime],
                       [HashChecksum]
         )
         VALUES (
                SOURCE.[client],
                SOURCE.[text],
                SOURCE.[cost_center],
                SOURCE.[posting_period],
                SOURCE.[profit],
                SOURCE.[document_type],
                SOURCE.[company_code],
                SOURCE.[Account],
                SOURCE.[Amount_In_Doc_Curr],
                SOURCE.[document_currency],
                SOURCE.[Amount_In_local_Curr],
                SOURCE.[Amount_In_Grp_Curr],
                SOURCE.[group],
                SOURCE.[posting_date],
                SOURCE.[assignment],
                SOURCE.[reference],
                SOURCE.[reference_key2],
                SOURCE.[reference_key3],
                SOURCE.[document_number],
                SOURCE.[document_header_text],
                GETDATE(),
                SOURCE.[HashChecksum]
         )

   OUTPUT $action INTO @SummaryOfChanges;

   DECLARE @RowsProcessed INT = 0;

   SELECT 
          @RowsProcessed = ISNULL([INSERT],0) + ISNULL([UPDATE],0) + ISNULL([DELETE],0)
   FROM (
         SELECT COUNT(*) ChangeCount, Change as ChangeType 
         FROM @SummaryOfChanges
         GROUP BY Change
   )Main
   PIVOT ( 
         MAX(ChangeCount)
         FOR ChangeType IN ([INSERT],[UPDATE],[DELETE])
   )Pvt;

   SELECT @RowsProcessed AS RowsProcessed;


CREATE OR ALTER TRIGGER [dbo].[tr_merge_personal_expense] 
ON personal_expense_staging 
AFTER INSERT AS

----- CASE 1: IF (ACCOUNT AND REF_KEY2) ARE MATCHED THEN UPDATE
IF EXISTS
(
  SELECT 
         *
  FROM   dbo.personal_expense p
         INNER JOIN inserted e
         ON p.[account] = e.[account] AND p.[reference_key2] = e.
         [reference_key2]
)
    BEGIN
        UPDATE target
          SET  
              target.[document_number] = source.[document_number],
              target.[client] = source.[client],
              target.[text] = source.[text],
              target.[cost_center] = source.[cost_center],
              target.[posting_period] = source.[posting_period],
              target.[profit] = source.[profit],
              target.[document_type] = source.[document_type],
              target.[company_code] = source.[company_code],
              target.[amount_in_doc_curr] = source.[amount_in_doc_curr],
              target.[document_currency] = source.[document_currency],
              target.[amount_in_local_curr] = source.[amount_in_local_curr],
              target.[amount_in_grp_curr] = source.[amount_in_grp_curr],
              target.[group] = source.[group],
              target.[posting_date] = source.[posting_date],
              target.[assignment] = source.[assignment],
              target.[reference] = source.[reference],
              target.[reference_key1] = source.[reference_key1],
              target.[reference_key3] = source.[reference_key3],
              target.[document_header_text] = source.[document_header_text],
              target.[last_updated_datetime] = GETDATE()
        FROM   personal_expense target
               INNER JOIN inserted source
               ON target.[account] = source.[account] 
               AND target.[reference_key2] = source.[reference_key2];
END;

        ------ CASE 2: IF (ACCOUNT AND REF_KEY2) ARE NOT MATCHED THEN INSERT
        IF NOT EXISTS
        (
          SELECT 
                 *
          FROM   dbo.personal_expense p
                 INNER JOIN inserted e
                 ON p.[account] = e.[account] AND p.[reference_key2] = e.
                 [reference_key2]
        )
            BEGIN
                INSERT INTO dbo.personal_expense
                (
                       [client],
                       [text],
                       [cost_center],
                       [posting_period],
                       [profit],
                       [document_type],
                       [company_code],
                       [account],
                       [amount_in_doc_curr],
                       [document_currency],
                       [amount_in_local_curr],
                       [amount_in_grp_curr],
                       [group],
                       [posting_date],
                       [assignment],
                       [reference],
                       [reference_key1],
                       [reference_key2],
                       [reference_key3],
                       [document_number],
                       [document_header_text],
                       [last_updated_datetime]
                )
                       SELECT 
                              source.[client],
                              source.[text],
                              source.[cost_center],
                              source.[posting_period],
                              source.[profit],
                              source.[document_type],
                              source.[company_code],
                              source.[account],
                              source.[amount_in_doc_curr],
                              source.[document_currency],
                              source.[amount_in_local_curr],
                              source.[amount_in_grp_curr],
                              source.[group],
                              source.[posting_date],
                              source.[assignment],
                              source.[reference],
                              source.[reference_key1],
                              source.[reference_key2],
                              source.[reference_key3],
                              source.[document_number],
                              source.[document_header_text],
                              GETDATE()
                       FROM   inserted source;
            END;

SO, you know that of duplicates, merge statement producing an error .所以,你知道of duplicates, merge statement producing an error Then simply remove the duplicates in your source clause, using DISTINCT :然后使用DISTINCT简单地删除源子句中的重复项:

SELECT DISTINCT *
FROM [dbo].[Personal_Expense_Staging]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM