如果存在UPDATE,则表示每行的INSERT

时间:2014-11-17 16:19:43

标签: sql-server insert-update

我有一个名为tableFrom的表想要插入一个名为tableTo的表中。插入工作正常,但如果我再次插入相同的值,我有一个重复的键错误。所以我想只更新已经存在的行。我知道命令ON DUPLICATE with MySQL,遗憾的是在SQL Server中丢失了。

如果我只想检查一个精确的行,很容易:

IF EXISTS PK = @PK

但是我试图在整张桌子上做这件事,而且我不知道是否有可能。我想用光标检查每一行,我是SQL的新手。

以下是我提出的建议:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
IF EXISTS   (
            SELECT 
                1 
            FROM 
                tableFrom F,
                tableTo T
            WHERE 
                T.product = F._product
            )
    BEGIN
        UPDATE
            tableTo
        SET
            T.something = F.something
        FROM
            tableTo T
                INNER JOIN 
                    tableFrom F
                ON
                    T.product = F._product
    END
ELSE
    BEGIN
        INSERT INTO tableTo
            (product, 
            something)
        SELECT
            F._product, 
            F.something
        FROM
            tableFrom F
    END
COMMIT TRANSACTION

UPDATE部分工作正常,但没有INSERT完成。

EDIT1:

试过这段代码:

MERGE tableTo AS T
USING tableFrom AS S
    ON (T.product= S._product)
WHEN NOT MATCHED BY TARGET
    THEN INSERT(product, something) VALUES(S._product, S.something)
WHEN MATCHED 
    THEN UPDATE SET T.Something= S.Something

出现以下错误:" MERGE'附近的语法错误。您可能需要将当前数据库的兼容级别设置为更高的值才能启用此功能。请参阅ALTER DATABASE的SET COMPATIBILITY_LEVEL选项的帮助。"

EDIT2:

我用Google搜索了上面的错误消息,似乎是由于MERGE语句之前最后一行末尾缺少分号。 MERGE命令工作正常!

2 个答案:

答案 0 :(得分:4)

使用Merge操作。

来自MSDN documentation

  

基于目标表执行插入,更新或删除操作   关于与源表的连接的结果。例如,你可以   通过在一个表中插入,更新或删除行来同步两个表   表基于另一个表中的差异。

答案 1 :(得分:4)

它没有丢失。 SQL Server实现了standard MERGE语句,该语句允许您指定在源和目标之间发生匹配时发生的情况。查看documentation以获取示例。

使用可能涉及许多列的条件进行匹配。 MERGE允许您在以下情况下执行INSERT,UPDATE或DELETE:

  • 根据条件
  • 找到匹配项
  • 匹配仅在源
  • 中发生
  • 匹配仅在目标
  • 中发生

这样,您可以更新现有行,插入仅存在于源中的行,删除仅出现在目标中的行。

在您的情况下,您可以执行以下操作:

MERGE tableTo AS T
USING tableFrom AS S
      ON (T.product= S._product)
WHEN NOT MATCHED BY TARGET
     THEN INSERT(product, something) VALUES(S._product, S.something)
WHEN MATCHED 
     THEN UPDATE SET T.Something= S.Something
OUTPUT $action, Inserted.*, Deleted.*;

此语句将根据需要插入或更新行,并返回使用OUTPUT子句插入或覆盖的值。