Как поместить выражение «if» в строку SQL?


190

Вот что я хочу сделать с моей базой данных MySQL .

Я хотел бы сделать:

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

Если бы это не вернуло ни одной строки, что возможно через if(dr.HasRows == false), я бы сейчас создал UPDATEв purchaseOrderбазе данных:

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

Как бы я мог сделать этот процесс немного короче?


4
База данных itemsOrdered имеет уникальный идентификатор itemsOrdered_IDи повторяющиеся purchaseOrder_IDзначения
Джон Эрнест Гуадалупе

1
purchaseorderбазы данных с другой стороны , имеет уникальный идентификаторpurchaseOrder_ID
John Ernest Гваделупской

Ответы:


411

По вашему конкретному запросу вы можете сделать:

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

Тем не менее, я могу догадаться, что вы цикл на более высоком уровне. Чтобы установить все такие значения, попробуйте это:

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
                     )

26
На самом деле в MySQL коррелированный подзапрос должен быть одним из наиболее эффективных подходов, при условии, что существует индекс для itemsOrdered.purchaseOrder_ID.
Гордон Линофф

8
@eggyal. , , Я согласен, что без индекса коррелированная версия, возможно, менее производительна, чем объединение (зависит от различных факторов, таких как умножение строк). С индексом, однако, это должно быть лучше, чем объединение, потому что оно должно остановить сканирование индекса при первом совпадении. Проверьте dev.mysql.com/doc/refman/5.5/en/… .
Гордон Линофф

53

Вы можете использовать UPDATEсинтаксис нескольких таблиц для выполнения ANTI-JOINмежду purchaseOrderи 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

47

Поскольку MySQL не поддерживает if exists(*Your condition*) (*Write your query*), вы можете достичь условия if, написав так:

(*Write your insert or update query*) where not exists (*Your condition*)

27

Вы также можете использовать следующий запрос, чтобы проверить, существует ли запись, а затем обновить ее:

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

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

4
Я изо всех сил пытаюсь увидеть, как это отвечает на вопрос вообще?
TheMayer

1
@ theMayer Я тоже, но это довольно хороший ответ
Габриэль

2
Поздравляем! Ваш код был выбран как запутанный код.
Вишванат Дальви

1
Я думаю , это пример того , что еще мы можем сделать с помощьюSQL
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

7
было бы здорово, если бы вы также объяснили ответ, ответы только с кодом не помогли бы будущим пользователям
Кумар Саурабх

8

после SQL Server 2008 обеспечить Mergeоперацию вставки, обновления и удаления на основе одного оператора сопоставления, что также позволяет присоединиться. Пример ниже может помочь вам.

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

Как это вы можете вставлять, обновлять и удалять в одном утверждении.

и для получения дополнительной информации вы можете обратиться к официальным документам на https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx


7

Если таблица содержит миллионы записей, следующий запрос будет работать быстро.

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

1

Вы можете объявить переменную, содержащую количество возвращенных результатов в запросе выбора. Затем вы можете запустить оператор обновления, если эта переменная больше 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'        
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.