Oracle SQL 从触发器中的连接更新 table 的正确语法是什么?
Oracle SQL What is the right syntax to Update a table from a join in a trigger?
我有 3 tables :
portees : 代表一条有几列的电线 (por_cur, 设备 A, 设备 B, ..., iqu_cur, 检查)
cab_portees : 表示线路上的特定设备(一条线路上可以有多个这些设备的实例),
列 (id, por_cur (来自 portees 的外键), ..., iqu_cur)
indice_qualite :表示其他两个 table 之一的 1 个属性,被认为是重要数据。列(table_name、attribut_name、...、iqu_cur、检查)
我们检查 table portees 和 cab_portees 中的数据以确保其正确,当检查一行时我们将 portees.examine 更新为“1”。我想触发自动更新 table indice_qualite :将 table 中的所有设备放入 examine = '1'.
我无法获得正确的语法,这是我的语法:
create or replace trigger PORTEES_EXAMINE_TRIGGER
AFTER UPDATE ON PORTEES
FOR EACH ROW
BEGIN
if :new.EXAMINE != :old.EXAMINE then
UPDATE (SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, PORTEES
WHERE PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND PORTEES.IQU_CUR = :old.IQU_CUR
UNION
SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, CAB_PORTEES
WHERE CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND CAB_PORTEES.POR_CUR = :old.POR_CUR)
SET INDICE_QUALITE.EXAMINE = :new.EXAMINE;
end if;
END PORTEES_EXAMINE_TRIGGER;
有什么想法吗?
你不能写连接更新查询。使用 Merge 进行连接。
MERGE INTO INDICE_QUALITE M USING
(SELECT EXAMINE,
INDICE_QUALITE.IQU_CUR
FROM INDICE_QUALITE,
PORTEES
WHERE PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND PORTEES.IQU_CUR = :old.IQU_CUR
UNION
SELECT EXAMINE,
INDICE_QUALITE.IQU_CUR
FROM INDICE_QUALITE,
CAB_PORTEES
WHERE CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND CAB_PORTEES.POR_CUR = :old.POR_CUR) T ON (M.IQU_CUR = T.IQU_CUR) WHEN MATCHED THEN
UPDATE
SET EXAMINE = :new.EXAMINE;
试试这个:
UPDATE (SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, PORTEES
WHERE PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND PORTEES.IQU_CUR = :old.IQU_CUR
UNION ALL
SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, CAB_PORTEES
WHERE CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND CAB_PORTEES.POR_CUR = :old.POR_CUR) t
SET t.EXAMINE = :new.EXAMINE;
但是,我不知道这是否适用于 UNION ALL
(当然它不适用于 UNION
)。此外,您应该更喜欢 ANSI 连接语法而不是旧的 Oracle 连接语法。
否则尝试:
UPDATE (SELECT INDICE_QUALITE.EXAMINE
FROM INDICE_QUALITE
JOIN CAB_PORTEES ON CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
WHERE PORTEES.IQU_CUR = :old.IQU_CUR) t
SET t.EXAMINE = :new.EXAMINE;
UPDATE (SELECT INDICE_QUALITE.EXAMINE
FROM INDICE_QUALITE
JOIN PORTEES ON CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
WHERE CAB_PORTEES.POR_CUR = :old.POR_CUR) t
SET t.EXAMINE = :new.EXAMINE;
请注意,仅当您在 CAB_PORTEES.IQU_CUR
和 INDICE_QUALITE.IQU_CUR
上具有 UNIQUE index/constraint 时,此类更新才有效
您可以这样重写查询:
UPDATE INDICE_QUALITE iq
SET iq.EXAMINE = :new.EXAMINE
WHERE EXISTS (SELECT 1
FROM PORTEES p
WHERE p.IQU_CUR = iq.IQU_CUR
AND p.IQU_CUR = :old.IQU_CUR
UNION ALL
SELECT 1
FROM CAB_PORTEES cp
WHERE cp.IQU_CUR = iq.IQU_CUR
AND cp.POR_CUR = :old.POR_CUR);
我已将所有规则放在更新语句的 exists
条件中。我不确定这是否可行,因为要求不明确 - 您没有解释任何内容,您只是提供了无效的查询。
我有 3 tables :
portees : 代表一条有几列的电线 (por_cur, 设备 A, 设备 B, ..., iqu_cur, 检查)
cab_portees : 表示线路上的特定设备(一条线路上可以有多个这些设备的实例), 列 (id, por_cur (来自 portees 的外键), ..., iqu_cur)
indice_qualite :表示其他两个 table 之一的 1 个属性,被认为是重要数据。列(table_name、attribut_name、...、iqu_cur、检查)
我们检查 table portees 和 cab_portees 中的数据以确保其正确,当检查一行时我们将 portees.examine 更新为“1”。我想触发自动更新 table indice_qualite :将 table 中的所有设备放入 examine = '1'.
我无法获得正确的语法,这是我的语法:
create or replace trigger PORTEES_EXAMINE_TRIGGER
AFTER UPDATE ON PORTEES
FOR EACH ROW
BEGIN
if :new.EXAMINE != :old.EXAMINE then
UPDATE (SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, PORTEES
WHERE PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND PORTEES.IQU_CUR = :old.IQU_CUR
UNION
SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, CAB_PORTEES
WHERE CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND CAB_PORTEES.POR_CUR = :old.POR_CUR)
SET INDICE_QUALITE.EXAMINE = :new.EXAMINE;
end if;
END PORTEES_EXAMINE_TRIGGER;
有什么想法吗?
你不能写连接更新查询。使用 Merge 进行连接。
MERGE INTO INDICE_QUALITE M USING
(SELECT EXAMINE,
INDICE_QUALITE.IQU_CUR
FROM INDICE_QUALITE,
PORTEES
WHERE PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND PORTEES.IQU_CUR = :old.IQU_CUR
UNION
SELECT EXAMINE,
INDICE_QUALITE.IQU_CUR
FROM INDICE_QUALITE,
CAB_PORTEES
WHERE CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND CAB_PORTEES.POR_CUR = :old.POR_CUR) T ON (M.IQU_CUR = T.IQU_CUR) WHEN MATCHED THEN
UPDATE
SET EXAMINE = :new.EXAMINE;
试试这个:
UPDATE (SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, PORTEES
WHERE PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND PORTEES.IQU_CUR = :old.IQU_CUR
UNION ALL
SELECT INDICE_QUALITE.EXAMINE FROM
INDICE_QUALITE, CAB_PORTEES
WHERE CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
AND CAB_PORTEES.POR_CUR = :old.POR_CUR) t
SET t.EXAMINE = :new.EXAMINE;
但是,我不知道这是否适用于 UNION ALL
(当然它不适用于 UNION
)。此外,您应该更喜欢 ANSI 连接语法而不是旧的 Oracle 连接语法。
否则尝试:
UPDATE (SELECT INDICE_QUALITE.EXAMINE
FROM INDICE_QUALITE
JOIN CAB_PORTEES ON CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
WHERE PORTEES.IQU_CUR = :old.IQU_CUR) t
SET t.EXAMINE = :new.EXAMINE;
UPDATE (SELECT INDICE_QUALITE.EXAMINE
FROM INDICE_QUALITE
JOIN PORTEES ON CAB_PORTEES.IQU_CUR = INDICE_QUALITE.IQU_CUR
WHERE CAB_PORTEES.POR_CUR = :old.POR_CUR) t
SET t.EXAMINE = :new.EXAMINE;
请注意,仅当您在 CAB_PORTEES.IQU_CUR
和 INDICE_QUALITE.IQU_CUR
您可以这样重写查询:
UPDATE INDICE_QUALITE iq
SET iq.EXAMINE = :new.EXAMINE
WHERE EXISTS (SELECT 1
FROM PORTEES p
WHERE p.IQU_CUR = iq.IQU_CUR
AND p.IQU_CUR = :old.IQU_CUR
UNION ALL
SELECT 1
FROM CAB_PORTEES cp
WHERE cp.IQU_CUR = iq.IQU_CUR
AND cp.POR_CUR = :old.POR_CUR);
我已将所有规则放在更新语句的 exists
条件中。我不确定这是否可行,因为要求不明确 - 您没有解释任何内容,您只是提供了无效的查询。