Comment mettre une «clause if» dans une chaîne SQL?

190

Alors, voici ce que je veux faire sur ma base de données MySQL .

Je voudrais faire:

SELECT *
    FROM itemsOrdered
    WHERE purchaseOrder_ID = '@purchaseOrdered_ID'
        AND status = 'PENDING'

Si cela ne renvoie aucune ligne, ce qui est possible grâce if(dr.HasRows == false), je créerais maintenant un UPDATEdans la purchaseOrderbase de données:

UPDATE purchaseOrder
    SET purchaseOrder_status = 'COMPLETED'
    WHERE purchaseOrder_ID = '@purchaseOrder_ID'

Comment pourrais-je raccourcir un peu ce processus?

John Ernest Guadalupe
la source
4
La base de données itemsOrdered a un identifiant unique appelé itemsOrdered_IDet a des purchaseOrder_IDvaleurs récurrentes
John Ernest Guadalupe
1
la purchaseorderbase de données d'autre part a l'identifiant uniquepurchaseOrder_ID
John Ernest Guadalupe

Réponses:

411

Pour votre requête spécifique, vous pouvez faire:

UPDATE purchaseOrder
    SET purchaseOrder_status = 'COMPLETED'
    WHERE purchaseOrder_ID = '@purchaseOrder_ID' and
          not exists (SELECT *
                      FROM itemsOrdered WHERE purchaseOrder_ID = '@purchaseOrdered_ID' AND status = 'PENDING'
                     )

Cependant, je suppose que vous faites une boucle à un niveau supérieur. Pour définir toutes ces valeurs, essayez ceci:

UPDATE purchaseOrder
    SET purchaseOrder_status = 'COMPLETED'
    WHERE not exists (SELECT 1
                      FROM itemsOrdered
                      WHERE itemsOrdered.purchaseOrder_ID = purchaseOrder.purchaseOrdered_ID AND
                            status = 'PENDING'
                      limit 1
                     )
Gordon Linoff
la source
26
En fait, dans MySQL, la sous-requête corrélée devrait être parmi les approches les plus efficaces, en supposant qu'il existe un index sur itemsOrdered.purchaseOrder_ID.
Gordon Linoff
8
@eggyal. . . Je conviens que sans index la version corrélée est peut-être moins performante que la jointure (dépend de divers facteurs, comme la multiplication des lignes). Avec un index, cependant, cela devrait être mieux qu'une jointure car cela devrait arrêter l'analyse d'index à la première correspondance. Vérifiez dev.mysql.com/doc/refman/5.5/en/… .
Gordon Linoff
53

Vous pouvez utiliser la UPDATEsyntaxe de plusieurs tables pour effectuer un ANTI-JOINentre purchaseOrderet itemsOrdered:

UPDATE purchaseOrder p LEFT JOIN itemsOrdered i
    ON p.purchaseOrder_ID = i.purchaseOrder_ID
   AND i.status = 'PENDING'
SET    p.purchaseOrder_status = 'COMPLETED'
WHERE  p.purchaseOrder_ID = '@purchaseOrder_ID'
   AND i.purchaseOrder_ID IS NULL
Eggyal
la source
47

Puisque MySQL ne prend pas en charge if exists(*Your condition*) (*Write your query*), vous pouvez obtenir une clause `` if '' en écrivant comme ceci:

(*Write your insert or update query*) where not exists (*Your condition*)
Ranjit Singh
la source
27

Vous pouvez également utiliser la requête suivante pour vérifier si l'enregistrement existe, puis le mettre à jour:

if not exists(select top 1 fromFROM itemsOrdered
    WHERE purchaseOrder_ID = '@purchaseOrdered_ID'
        AND status = 'PENDING' )
Begin

UPDATE purchaseOrder 
    SET purchaseOrder_status = 'COMPLETED'
    WHERE purchaseOrder_ID = '@purchaseOrder_ID

End
Santosh Shirkar
la source
22
Select FROM t1
    WHERE s11 > ANY
        (SELECT col1,col2 FROM t2
            WHERE NOT EXISTS
                (SELECT * FROM t3
                    WHERE ROW(5*t2.s1,77)=
                        (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
                            (SELECT * FROM t5) AS t5)));
sikandar bakht syed
la source
4
J'ai du mal à voir comment cela répond à la question?
theMayer
1
@theMayer Moi aussi mais c'est une assez bonne réponse
Gabriel
2
Félicitations, votre code a été sélectionné comme code obscurci.
Vishwanath Dalvi
1
Je suppose que c'est un exemple de ce que nous pouvons faire d'autre en utilisantSQL
Top-Master
13
if not exists(select top 1 fromFROM itemsOrdered
    WHERE purchaseOrder_ID = '@purchaseOrdered_ID'
        AND status = 'PENDING' )
Begin

UPDATE purchaseOrder 
    SET purchaseOrder_status = 'COMPLETED'
    WHERE purchaseOrder_ID = '@purchaseOrder_ID

End
CH Hamza Ahmad
la source
7
ce sera formidable si vous expliquez également la réponse, les réponses de code uniquement ne sont pas utiles pour les futurs utilisateurs
Kumar Saurabh
8

après sql server 2008 fournir Mergepour insérer, mettre à jour et supprimer l'opération basée sur une seule déclaration de correspondance, également qui vous permet de rejoindre. l'exemple ci-dessous pourrait vous aider.

MERGE Target AS T
USING Source AS S
ON (T.EmployeeID = S.EmployeeID) 
WHEN NOT MATCHED BY TARGET AND S.EmployeeName LIKE 'S%' 
    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName)
WHEN MATCHED 
    THEN UPDATE SET T.EmployeeName = S.EmployeeName
WHEN NOT MATCHED BY SOURCE AND T.EmployeeName LIKE 'S%'
    THEN DELETE 
OUTPUT $action, inserted.*, deleted.*;

comme ça, vous pouvez insérer, mettre à jour et supprimer en une seule déclaration.

et pour plus d'informations, vous pouvez consulter les documents officiels sur https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

Lalji Dhameliya
la source
7

Si la table contient des millions d'enregistrements, la requête suivante fonctionnera rapidement.

UPDATE PO
SET PO.purchaseOrder_status = 'COMPLETED'
FROM purchaseOrder PO
LEFT OUTER JOIN itemsOrdered IOD ON IOD.purchaseOrder_ID = PO.purchaseOrdered_ID and IOD.status = 'PENDING'
WHERE IOD.purchaseOrder_ID IS NULL
Amit Prajapati
la source
1

Vous pouvez déclarer une variable contenant le nombre de résultats renvoyés sur la requête de sélection. Vous pouvez ensuite exécuter l'instruction de mise à jour si cette variable est supérieure à 0

    Declare @ResultCount int
    SELECT @ResultCount = count(*) FROM itemsOrdered WHERE purchaseOrder_ID = '@purchaseOrdered_ID' AND status = 'PENDING'        
    If @ResultCount > 0
UPDATE purchaseOrder SET purchaseOrder_status = 'COMPLETED' WHERE purchaseOrder_ID = '@purchaseOrder_ID'        
Alireza
la source