用于更新插入的无参数存储过程

Parameterless stored procedure to update insert

我正在处理应该在远程 table 中插入或更新行的存储过程。我尝试使用 MERGE,但是当目标 table 是远程时无法使用 MERGE。

有人可以告诉我如何在存储过程中进行更新吗?我是否需要先将记录读入临时 table 然后比较值?我有兴趣更新的列值是 FlagValue。

更新

我能够在另一台服务器上创建链接服务器并翻转目标和源。

我正在整理一个使用 MERGE 的存储过程,我想知道是否有人可以帮助我检查代码并让我知道它是否看起来不错。如果 sku 已经位于目标 table 但 FlagValue 值不同,则代码基本上必须更新 FlagValue 列,并且它必须插入也仅限于 SELECT 的记录在 USING ( ) 作为 SOURCE,而不是插入来自 table 产品的所有记录。

更新 T-SQL:

ALTER PROCEDURE [dbo].[mn_RecordInfo_Upsert]
AS
BEGIN

    --Synchronize the target table with refreshed data from source table
    MERGE [dbo].[RecordInfo] AS [t]
    USING
        ( SELECT TOP 100 PERCENT
            [p].[ProductID]
          , [p].[Flag]
          FROM
            [server].[db].[dbo].[Product] [p]  -- Remote linked server table
          WHERE
            (
              [Category] = 2
              OR [Description] = 'This type of product' )
            AND LEN([ProductID]) = 10
            AND [ProductID] LIKE 'P0%'
          ORDER BY
            [Date] DESC
        ) AS [s]
    ON ( [t].[PID] = [s].[ProductID] ) 

    --When records are matched, update the records if there is any change
    WHEN MATCHED AND [t].[Flag] <> [s].[Flag]
        AND [t].[PID] = [s].[ProductID] THEN
        UPDATE SET
               [t].[Flag] = [s].[Flag]                          

    --When no records are matched, insert the incoming records from source table to target table
    WHEN NOT MATCHED BY TARGET THEN
        INSERT
               (
                 [PID]
               , [Flag] )
        VALUES (
                 [s].[ProductID]
               , [s].[Flag] )       

    --SELECT @@ROWCOUNT;
    OUTPUT
        $action AS [DMLAction]
      , [inserted].*
      , [deleted].*;
END;

感谢您的推荐。

如果我将您的问题理解为您所写的内容是否符合您的想法?我相信是的。您的更新看起来不错,尽管再次加入 target.sku = source.sku 是多余的。单个合并语句中的所有不同语句(例如 when matchedwhen not matched by sourcewhen not matched by target)将使用顶部声明的连接条件,因此您无需再次指定它。要考虑的另一件事是 FlagValue 是否可以为空。如果是这样,检查 target.FlagValue != source.FlagValue 将 return 为假,因为 null != null.

至于你的插页,你是对的。它只会使用您定义的子查询的结果并别名为 source(旁注,尽管 MSDN 喜欢将它们别名为 sourcetarget,但我倾向于 st 因为它们不是保留关键字,并且在您最终使用 sourcetarget 作为 actual 关键字时避免混淆,例如,when not matched by target。重点是,您可以随意为它们起别名;您不限于这两个关键字)。

如果您想了解执行过程中发生的事情,您可以做两件主要的事情。第一种是在末尾使用 OUTPUT 子句;像

这样简单的东西
...
(
     [SOURCE].[SKU],
     [SOURCE].[FlagValue]
)
output $action as DMLAction, inserted.*, deleted.*

如果您发现 MERGE 难以使用,第二种方法是考虑将它们写成两个单独的语句而不是 MERGE;一个 insert 和一个 update。在大多数情况下,MERGE 无论如何都会这样做,因此您不会失去性能,而且通常比 [=34] 更容易区分 insertupdate 语句=] 根据我的经验。

此外,在通过链接服务器加入时,我必须特别注意。有时它会表现良好,但有时它会完全做自己的事情。如果远程 table 很大,您可能最终会扫描整个 table 并将其通过链接服务器传输,即使您不希望它得到任何接近计划的东西table 本地。