2009-04-08 12 views
4

J'ai deux tables. Une chaîne est/ID look simple up:Mise à jour SQL avec une jointure?

strTable:

 
str_key String 
0  'a' 
1  'b' 

où les cordes sont uniques. L'autre est plus complexe, et comprend le string_id partagé

ValTable:

 
str_key other_key val 
0  0  1.234 
0  1  1.567 
1  0  1.890 

Maintenant, je veux faire une mise à jour sur ValTable, en utilisant une chaîne que je recherche pour obtenir le str_key via strTable. La simple mise à jour serait:

UPDATE ValTable SET val = 2.124 WHERE str_key = 0 AND other_key = 1 LIMIT 1 
IF @@ROWCOUNT=0 INSERT INTO ValTable VALUES (0,1,2.124); 

Alors, comment puis-je modifier cette recherche pour inclure le str_key avec une chaîne de caractères « a »? Je suppose que j'ai besoin d'une jointure, mais je n'ai jamais fait de jointure dans une mise à jour. Ou puis-je simplement ajouter plus à ma clause where?

+0

Vous n'avez pas pour vos tables DDL, mais en supposant que str_key et other_key faire le PK pour votre ValTable, est-il une raison que vous avez le « LIMIT 1 »? Même si ce n'est pas le PK, il semble étrange d'utiliser LIMIT ici –

+0

Je ne savais pas si cela entraînerait un balayage de la table entière sans la limite, mais je suppose que c'est assez intelligent pour savoir que la clé composée est * la touche * et n'affecte qu'une seule ligne. –

Répondre

14

Voici la syntaxe dont vous avez besoin:

UPDATE v 
SET  val = 2.124 
FROM ValTable v 
     INNER JOIN 
       StringTable s 
       ON v.str_key = s.str_key 
WHERE s.String = 'a' 
AND  v.other_key = 1 

IF @@ROWCOUNT = 0 
BEGIN 

     INSERT 
     INTO ValTable 
     SELECT str_key, 1, 2.124 
     FROM StringTable 
     WHERE String = 'a' 

END 
+0

Comment modifier la deuxième ligne? Est-ce que je peux juste faire ceci: SI @@ ROWCOUNT = 0 INSERT INTO v VALEURS (v.str_key, 1, 2.124) Ou ai-je besoin de re-déterminer v.str_key en utilisant une autre jointure? –

1

L'exemple ci-dessus par David M est valide et travaille. En fonction de la taille de votre table, vous pouvez éviter les "mises à jour aveugles" car cela peut causer des problèmes de performance sur des tables très grandes. Notez les indications de table dans le fichier IF EXISTS().

IF EXISTS(
     SELECT 
      * 
     FROM 
      ValTable v WITH(NOLOCK) 
      INNER JOIN StringTable s WITH(NOLOCK) ON v.str_key = s.str_key 
     WHERE 
      s.String = 'a' 
     AND v.other_key = 1 
    ) 
BEGIN 
    UPDATE 
     v 
    SET  
     val = 2.124 
    FROM  
     ValTable v 
     INNER JOIN StringTable s ON v.str_key = s.str_key 
    WHERE 
     s.String = 'a' 
    AND v.other_key = 1 
END 
ELSE 
BEGIN 
    INSERT INTO ValTable 
     --(You should define your columns here, You didn't provide a sample schema so I don't know what your columns are.) 
     --(Col1,COl2,COl3,etc...) 
    SELECT 
     str_key, 1, 2.124 
    FROM  
     StringTable 
    WHERE 
     String = 'a' 
END 
Questions connexes