2017-07-12 2 views
0

Je travaille sur une procédure stockée censée insérer ou mettre à jour des lignes dans une table distante. J'ai essayé d'utiliser MERGE, mais il n'est pas possible d'utiliser MERGE lorsque la table cible est distante. Est-ce que quelqu'un peut me montrer comment puis-je faire la mise à jour dans le sproc? Dois-je d'abord lire les enregistrements dans une table temporaire, puis comparer les valeurs? La valeur de la colonne que je suis intéressé à mettre à jour est FlagValue.Procédure stockée sans paramètre pour mettre à jour l'insertion

MISE À JOUR

j'ai pu créer un serveur lié sur l'autre serveur et déplacé la cible et la source.

Je mets ensemble une procédure stockée qui utilise MERGE, je me demandais si quelqu'un pouvait me aider à examiner le code et laissez-moi savoir s'il semble ok. Le code doit fondamentalement mettre à jour la colonne FlagValue si le sku réside déjà dans la table cible mais la valeur FlagValue est différente, et il doit insérer des enregistrements qui sont également limités à SELECT dans USING() comme SOURCE, et pas tout insérer enregistrements du produit de table.

MISE À JOUR 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; 

Merci pour vos recommandations.

+3

Une solution consiste à créer la procédure stockée sur le serveur distant. Ensuite, vous pouvez utiliser 'MERGE'. – Eric

+1

Quelle MISE À JOUR? Montrez-nous la mise à jour que vous voulez exécuter. – RBarryYoung

+0

Je viens de l'ajouter. Ma faute. –

Répondre

1

Si je comprends bien votre question pour être juste ce que vous avez écrit ce que vous pensez ne le fait? Je le crois. Votre mise à jour semble correcte, bien que rejoindre à nouveau target.sku = source.sku soit redondant. Toutes les instructions différentes dans une seule instruction de fusion (par exemple, when matched, when not matched by source, when not matched by target) utiliseront les critères de jointure déclarés en haut, vous n'avez donc pas besoin de le spécifier à nouveau. Une autre chose à considérer est si FlagValue peut être nulle. Si c'est le cas, vérifiez que target.FlagValue != source.FlagValue retournera false depuis null != null.

En ce qui concerne votre insertion, vous avez raison. Il utilisera uniquement les résultats de la sous-requête que vous avez définie et alias source (note secondaire, bien que MSDN aime les alias source et target, j'ai tendance à aimer s et t car ils ne sont pas des mots-clés réservés et évite la confusion lorsque vous terminez en utilisant source et target comme réels mots-clés lorsque vous tapez, par exemple, when not matched by target Le fait est, vous pouvez les alias ce que vous voulez, vous n'êtes pas limité à ces deux mots-clés).

Si vous voulez une visibilité sur ce qui se passe pendant l'exécution, vous pouvez faire deux choses principales. La première consiste à utiliser une clause OUTPUT à la fin; quelque chose d'aussi simple que

... 
(
    [SOURCE].[SKU], 
    [SOURCE].[FlagValue] 
) 
output $action as DMLAction, inserted.*, deleted.* 

Si vous trouvez MERGE maladroites de travailler avec, la seconde approche serait de considérer l'écriture comme deux déclarations séparées au lieu d'un MERGE; un insert et un update. Pour la plupart, un MERGE fait ça de toute façon, vous ne perdez pas sur peformance, et il est généralement plus facile de décortiquer une déclaration insert ou update qu'un merge dans mon expérience.

En outre, je dois donner un mot obligatoire de prudence lors de l'adhésion sur un serveur lié. Parfois, cela fonctionnera bien, mais parfois, il va faire son propre truc entièrement.Si la table distante est grande, vous risquez de finir par balayer la totalité de la table et de la rediriger vers le serveur lié, même si vous ne vous attendez pas à ce qu'elle soit proche d'un plan si la table est locale.

+1

Salut Xedni, je mets à jour mon post avec la dernière version de mon code. Je pense qu'il fait ce que j'ai besoin de faire. Merci beaucoup pour votre explication. –