2010-06-04 6 views
3

J'ai une instruction select qui joint deux tables et récupère des informations. Je voudrais mettre à jour tous les enregistrements sur l'un de ces tableaux (trouvés dans le select) avec des informations contenues dans le select. Le select ressemble à ceci:SQL - Comment effectuer une mise à jour par lots compte tenu des résultats d'une sélection

SELECT account.id 
     document.id 
FROM customer INNER JOIN account ON 
      (customer.firstname = account.firstname AND 
      customer.lastname = account.lastname AND 
      customer.phone = account.phone) 
     INNER JOIN document ON 
      customer.id = document.customerid 
WHERE document.accountid IS NULL; 

En anglais, un document peut appartenir aux clients et aux comptes. Je recherche les enregistrements de compte qui correspondent aux enregistrements clients dans lesquels le document appartient au client, mais pas le compte.

Maintenant, je peux manuellement passer par les résultats et exécuter ceci:

UPDATE document 
SET  accountid = /*account.id*/ 
WHERE id = /*document.id*/; 

qui fonctionne comme je le voudrais, mais il y a une bonne quantité de documents qui correspondent à ma requête et je voudrais le faire dans une seule déclaration si je pouvais.

Répondre

6
UPDATE document, account, customer 
SET documnet.accountid = account.id 
WHERE (customer.firstname = account.firstname AND customer.lastname = account.lastname AND customer.phone = account.phone) 
AND customer.id = document.customerid 
AND document.accountid IS NULL; 

Cela devrait le faire tout en un aller

+0

+1 J'écrivais une solution similaire acheter vous étiez plus rapide! :) –

+0

intéressant. J'ai essayé ceci dans un jeu de données de test (copie de réel) et il a produit plus de mises à jour que des rangées dans la requête originale. Je vais devoir y regarder de plus près. –

+0

Probablement en raison de la première jointure. –

2

Une solution plus conforme à la norme ANSI serait la suivante:

Update document 
Set accountid = (
       Select Min(A1.id) 
       From customer As C1 
        Join account As A1 
         On A1.firstname = C1.firstname 
          And A1.lastname = C1.lastname 
          And A1.phone = C1.phone 
       Where C1.id = document.Id 
       ) 
Where accountid Is Null 

J'utilise Min(A1.id) pour faire en sorte que je reçois au plus un account.id pour les informations client données. Une jointure dans une clause Update n'est pas officiellement prise en charge par la spécification SQL car elle crée des ambiguïtés dans la mise à jour lorsque la même ligne peut être mise à jour avec des valeurs différentes.

Questions connexes