【问题标题】:Stored procedure that compares Table_1 and Table_2 and updates Table_2 according to data changed in Table_1比较 Table_1 和 Table_2 并根据 Table_1 中更改的数据更新 Table_2 的存储过程
【发布时间】:2018-08-29 09:48:29
【问题描述】:

假设我有两个表 Table_1 和 Table_2。

两者都有相同的列。

@Table_1

| Id | Col1 | Col2 | Col3 |
| 1  |   a  |   b  |  c   |
| 2  |   d  |   e  |  f   |

@Table_2

| Id | Col1 | Col2 | Col3 |
| 1  |   a  |   0  |  0   |
| 3  |   z  |   z  |  y   |

我如何编写将从Table_1 获取行的存储过程,将该行的每一列与Table_2 中的行进行比较,并相应地更新Table_2 列。如果在Table_2 中找不到Table_1 中的行,则只需插入即可。

现在。我意识到INSERT 很容易写,它可能看起来像

insert into @Table_2(col1, col2, col3)
select col1, col2, col3 from @Table_1 where id = @id

存储过程执行后Table_2的最终结果应该是这样的

@Table_2

| Id | Col1 | Col2 | Col3 |
| 1  |   a  |   b  |  c   |
| 2  |   d  |   e  |  f   |
| 3  |   z  |   z  |  y   |

Table_1的每一行和每一列与Table_2中的数据进行比较如何?

@Martyn Meeks 的答案作为两个单独的陈述!

根据用户@SQL_M 使用MERGE 提供的https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ 语句并不完美,但可以工作

@Jayasurya Satheesh 的脚本也可以,但使用 MERGE 语句

【问题讨论】:

    标签: sql sql-server database stored-procedures stored-functions


    【解决方案1】:

    如果您担心上述 MERGE 语句的潜在问题,您可以在两个单独的语句中进行处理

        UPDATE T2
        SET T2.Col1 = T1.Col1,
            T2.Col2 = T1.Col2,
            T2.Col3 = T1.Col3
        FROM @Table_2 T2
        INNER JOIN @Table_1 T1
        ON T2.Id = T1.Id
    
        INSERT INTO @Table_2 (Id,Col1,Col2,Col3)
        SELECT T1.Id,T1.Col1,T1.Col2,T1.Col3
        FROM @Table_1 T1
        WHERE NOT EXISTS (SELECT 1 FROM @Table_2 T2 WHERE T2.Id = T1.Id)
    

    编辑:按照 Jayasurya 的建议切换更新和插入语句。 否则新插入的行会被更新以及被插入,这是不必要的

    【讨论】:

    • 谢谢!将避免MERGE 语句
    • 我宁愿先进行更新,然后再进行插入,否则,您还将更新新插入的记录,这只是浪费时间
    • 是的,非常好。他们绝对应该轮换
    • @MartynMeeks 我应该如何切换它们?
    • 将更新语句放在插入语句之前。这样,正如 Jayasurya 所说,更新不会对现有行进行操作。我已经更改了答案以说明这意味着什么
    【解决方案2】:

    使用单个语句插入和更新可以使用SQL Merge Join实现

    像下面这个例子:

    MERGE Table1 T1
        USING Table2 T2
            ON T1.Id = T2.Id
        WHEN MATCHED
            UPDATE SET 
                T1.Col1 = T2.Col1,
                T1.Col2 = T2.Col2,
                T1.Col3 = T2.Col3
        WHEN NOT MATCHED BY TARGET
            INSERT(COL1,COL2,COL3)
            VALUES(T2.COL1,T2.COL2,T2.COL3)
    

    如果根据 Id 找到匹配项,我将更新 Table1 上的记录,否则如果没有匹配项则插入记录

    【讨论】:

    • 虽然这是真的,但我不建议这样做,但使用合并有一些潜在的缺点:mssqltips.com/sqlservertip/3074/…
    • 这确实有效。但需要在脚本中切换Table_1 和Table_2 的位置。谢谢!
    • @TheOneAndOnlyNoobofCSharp 只有两条单独的语句,一条用于插入,一条用于更新。
    • @SQL_M 谢谢。 Artcile 仅提及 Sql Server 2008。这些错误和“功能”是否适用于 SQL 2016 等较新的 Sql 服务器?
    【解决方案3】:

    创建一个 MERGE 语句。

    CREATE PROCEDURE [dbo].[IMPORT_Data]
    
    AS
    
    SET NOCOUNT ON;
    
    MERGE Table1 AS TRGT
    USING Table2 AS SRCE
       ON SRCE.Id = TRGT.Id
    WHEN MATCHED THEN UPDATE 
            SET TRGT.Col1 = SRCE.Col1,
                TRGT.Col2 = SRCE.Col2,
                TRGT.Col3 = SRCE.Col3,
                TRGT.Col4 = SRCE.Col4
    WHEN NOT MATCHED BY TARGET THEN 
                INSERT
                (
                    Col1,
                    Col2,
                    Col3,
                    Col4
                )
                VALUES
                (
                    SRCE.Col1,
                    SRCE.Col2,
                    SRCE.Col3,
                    SRCE.Col4
                )
    WHEN NOT MATCHED BY SOURCE THEN 
              DELETE;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-11
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      相关资源
      最近更新 更多