¿Cómo pongo una 'cláusula if' en una cadena SQL?

190

Entonces, esto es lo que quiero hacer en mi base de datos MySQL .

Me gustaría hacer:

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

Si eso no devuelve ninguna fila, lo cual es posible a través de if(dr.HasRows == false), ahora crearía un UPDATEen la purchaseOrderbase de datos:

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

¿Cómo podría hacer este proceso un poco más corto?

John Ernest Guadalupe
fuente
44
la base de datos de itemsOrdered tiene una identificación única llamada itemsOrdered_IDy tiene purchaseOrder_IDvalores recurrentes
John Ernest Guadalupe
1
la purchaseorderbase de datos, por otro lado, tiene la identificación únicapurchaseOrder_ID
John Ernest Guadalupe

Respuestas:

410

Para su consulta específica, puede hacer:

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'
                     )

Sin embargo, podría suponer que estás haciendo un bucle en un nivel superior. Para establecer todos estos valores, intente esto:

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
fuente
26
En realidad, en MySQL, la subconsulta correlacionada debería estar entre los enfoques más eficientes, suponiendo que haya un índice en itemsOrdered.purchaseOrder_ID.
Gordon Linoff
8
@eggyal. . . Estoy de acuerdo en que sin un índice, la versión correlacionada es quizás menos eficaz que la unión (depende de varios factores, como la multiplicación de filas). Sin embargo, con un índice, debería ser mejor que una unión porque debería detener el escaneo del índice en la primera coincidencia. Consulte dev.mysql.com/doc/refman/5.5/en/… .
Gordon Linoff
53

Puede usar la UPDATEsintaxis de varias tablas para efectuar un ANTI-JOINentre purchaseOrdery 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
fuente
47

Como MySQL no es compatible if exists(*Your condition*) (*Write your query*), puede lograr una 'cláusula if' escribiendo así:

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

También puede usar la siguiente consulta para verificar si el registro existe y luego actualizarlo:

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
fuente
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
fuente
44
¿Me cuesta ver cómo responde esto a la pregunta?
theMayer
1
@theMayer Yo también, pero es una respuesta bastante agradable
Gabriel
2
Felicitaciones, su código ha sido seleccionado como un código ofuscado.
Vishwanath Dalvi
1
Supongo que este es un ejemplo de qué más podemos hacer usandoSQL
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
fuente
77
será genial si explicas la respuesta también, las respuestas de solo código no son útiles para futuros usuarios
Kumar Saurabh
8

después de que sql server 2008 proporcione Mergepara insertar, actualizar y eliminar la operación basada en una declaración de coincidencia única, también eso le permite unirse. El ejemplo de ejemplo a continuación puede ser de ayuda.

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.*;

De esta manera, puede insertar, actualizar y eliminar en una sola declaración.

y para obtener más información, puede consultar documentos oficiales en https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

Lalji Dhameliya
fuente
7

Si la tabla contiene millones de registros, la siguiente consulta funcionará rápidamente.

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
fuente
1

Puede declarar una variable que contenga el número de resultados devueltos en la consulta de selección. Luego puede ejecutar la declaración de actualización si esta variable es mayor que 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
fuente