【问题标题】:Trigger on one table field works for all table fields在一个表字段上触发适用于所有表字段
【发布时间】:2012-07-28 20:26:00
【问题描述】:

我有一个触发器,用于表中的几个字段。但由于某种原因,如果另一个字段被更改(未在触发器中定义),那么它仍然会触发。

CREATE OR REPLACE TRIGGER INTEGRATION_EMPLOYMENT
    AFTER UPDATE OF start_day_of_employment, end_of_employment ON hr_employment_data
    FOR EACH ROW
    DECLARE
    BEGIN
         IF UPDATING THEN
            MERGE INTO ad_integration intg USING dual ON (intg.user_id = :NEW.user_id AND intg.integrated = 'NO')
            WHEN MATCHED THEN
                UPDATE SET
                         intg.start_day_of_employment = decode(:NEW.start_day_of_employment, NULL, ' ', :NEW.start_day_of_employment),
                         intg.end_of_employment = decode(:NEW.end_of_employment, NULL, ' ', :NEW.end_of_employment),
                         intg.manager_status = :NEW.manager_status,
                         intg.pid = (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id),
                         intg.network_access_start_date = (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id)
             WHEN NOT MATCHED THEN
                INSERT (intg.user_id, intg.start_day_of_employment, intg.end_of_employment, intg.manager_status, intg.pid, intg.network_access_start_date
                VALUES (:NEW.user_id, :NEW.start_day_of_employment, :NEW.end_of_employment, :NEW.manager_status, (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id), (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id));
END IF;

END HR_ADINTEGRATION_EMPLOYMENT;

是因为使用 DUAL 还是我遗漏了什么?

干杯! :-)

【问题讨论】:

  • 可能您有另一个未指定列的触发器。
  • 如何更新 HR_EMPLOYMENT_DATA?如果您通过某种用户界面对其进行更新,则用户界面可能会更新所有列,即使只有某些列的值发生了更改。此外,您是否有充分的理由不使用视图按需从 HR_EMPLOYMENT_DATA 中查找值(而不是使用触发器来尝试使 AD_INTEGRATION 保持最新)?使用触发器很难正确地做到这一点。 HR_EMPLOYMENT_DATA 上有插入和删除触发器吗? AD_INTEGRATION 上的更新和插入触发器怎么样?
  • 是的,有一些触发器是罪魁祸首,所以我想使用视图是最好的选择。 (为什么我以前没有想到这一点?)
  • 那么,为什么会触发呢?这仍然没有答案,Brian 的猜测是否正确,即使没有更改,用户界面也会更新所有列?我看不出触发器有什么问题。除了非常聪明的评论,您可以使用视图而不是保留冗余数据。

标签: oracle plsql oracle11g plsqldeveloper


【解决方案1】:

如果您想保持结构不变并且仅在特定字段更改时处理触发器,那么只需进行快速比较(新代码行 7 和 8):

CREATE OR REPLACE TRIGGER INTEGRATION_EMPLOYMENT
AFTER UPDATE OF start_day_of_employment, end_of_employment ON hr_employment_data
FOR EACH ROW
DECLARE
BEGIN
     IF UPDATING 
        AND (:NEW.start_day_of_employment <> :OLD.start_day_of_employment
        OR   :NEW.end_of_employment <> :OLD.end_of_employment)  THEN
        MERGE INTO ad_integration intg USING dual ON (intg.user_id = :NEW.user_id AND intg.integrated = 'NO')
        WHEN MATCHED THEN
            UPDATE SET
                     intg.start_day_of_employment = decode(:NEW.start_day_of_employment, NULL, ' ', :NEW.start_day_of_employment),
                     intg.end_of_employment = decode(:NEW.end_of_employment, NULL, ' ', :NEW.end_of_employment),
                     intg.manager_status = :NEW.manager_status,
                     intg.pid = (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id),
                     intg.network_access_start_date = (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id)
         WHEN NOT MATCHED THEN
            INSERT (intg.user_id, intg.start_day_of_employment, intg.end_of_employment, intg.manager_status, intg.pid, intg.network_access_start_date
            VALUES (:NEW.user_id, :NEW.start_day_of_employment, :NEW.end_of_employment, :NEW.manager_status, (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id), (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id));
END IF;

END HR_ADINTEGRATION_EMPLOYMENT;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多