Ваш DELETE ссылается на таблицу PORT дважды.Для пояснения давайте сначала изменим инструкцию, чтобы включить псевдонимы таблиц:
DELETE FROM PORT p1
WHERE EXISTS
(SELECT * FROM port p2 LEFT JOIN device on p2.fkdevice = device.pkid
where p2.fkjacket = :old.pkid
and device.fkdevice_type = 1);
Обратите внимание, что подзапрос не коррелируется с p1
.Другими словами, результат этого подзапроса будет одинаковым для каждой строки в PORT, которая рассматривается для удаления.Таким образом, вы либо удалите все строки, либо ни одной строки.
(Также странно, что вы используете LEFT JOIN, когда у вас есть предикат без объединения во внешней таблице. Но это в худшем случае проблема эффективностии, скорее всего, просто сбивает с толку любого, кто читает ваш код.)
Я считаю, что вам нужно:
DELETE FROM PORT
WHERE fkjacket = :old.pkid
AND EXISTS
(SELECT NULL FROM device
WHERE device.pkid = port.fkdevice
AND device.fkdevice_type=1);
И, похоже, ОБНОВЛЕНИЕ имеет ту же проблему;даже если в настоящее время он дает ожидаемые результаты, я уверен, что это просто удача из-за данных, которые вы тестируете.Я думаю, что это можно упростить до:
UPDATE PORT
set port.fkjacket = null, port.fkport = null
WHERE port.fkjacket = :old.pkid
AND EXISTS
(SELECT NULL FROM device
WHERE port.fkdevice = device.pkid
AND device.fkdevice_type <> 1);
Обратите внимание, что оператору EXISTS все равно, что если какие-либо столбцы будут возвращены его подзапросом;только ли строки возвращены вообще.