【问题标题】:PLSQL Merge - Update while row not existingPLSQL 合并 - 行不存在时更新
【发布时间】:2015-06-10 22:28:56
【问题描述】:

我有三个表用户、办公室和角色映射。用户 ID 将是针对办公室经理和办公室负责人的办公室表的 FK。角色和用户 ID 将映射到角色映射表中,如下所示。 删除办公室时,办公室表的活动列将更新为“N”。 当一个办公室被删除时,我必须检查办公室经理是否作为任何其他办公室的办公室经理出现。 (同一个人也可以是另一个市场的经理) 如果他不是,那么我必须通过将 Active 标志更新为“N”来删除角色映射表中的条目

表用户

User ID | User Name |
--------------------------
1       |   Mark    |

2       |   George  |

3       |   Rick    |

4       |   Alex    |

办公桌

Office ID   | Office Name   | Office Manager| Office Head   |   Active  |
---------------------------------------------------------------------------
1           |   Off1        |   1           |   2           |   Y       |

2           |   Off2        |   1           |   4           |   Y       |

角色映射

User ID |   User Role       |   Active  |
---------------------------------------------
    1   |   Office Manager  |   Y       |

    2   |   Office Head     |   Y       |

    4   |   Office Head     |   Y       |

所以在这个例子中,如果我删除 Office 2,那么我需要将角色映射表中的第三个条目更新为以下内容 办公室经理角色映射将保持不变,因为同一用户也是 Off1 的经理。

角色图——更新后

User ID |   User Role       |   Active  |
-------------------------------------------
    1   |   Office Manager  |   Y       |

    2   |   Office Head     |   Y       |

    4   |   Office Head     |   N       |

我不确定如何在 pl/sql 中实现这个查询。有人可以在这里指导我吗?

【问题讨论】:

  • 我认为 MERGE 在这里不会有用。我会创建一个触发器以避免每次删除后手动更新。

标签: sql oracle merge


【解决方案1】:

我认为在这种情况下不使用merge 会更安全。删除办公室或将其状态更新为非活动后 运行这个update:

update role_map set active = 'N'
  where (user_role = 'Office Head' 
    and not exists (
      select 1 from office 
        where office_head = role_map.user_id and active = 'Y'))
    or (user_role = 'Office Manager' 
    and not exists (
      select 1 from office 
        where office_manager = role_map.user_id and active = 'Y'));

我不确定是否需要表role_map,可能可以将其替换为视图,但也许您存储了一些其他数据。

【讨论】:

  • 谢谢。这是我试图编写的查询。
【解决方案2】:

如果您已经从 OFFICE 表中删除了该行,您可以检查 OFFICE 表中存在的员工是否具有活动角色,然后像这样进行简单的更新 -

UPDATE ROLE_MAP 
   SET active='N' 
 where user_id not in 
    (SELECT office_manager from office
     UNION ALL 
     SELECT office_head from office)

【讨论】:

    【解决方案3】:

    PLSQL 合并 - 行不存在时更新

    我认为您不能在 MERGE 语句中使用 WHEN NOT MATCHED 来执行 UPDATE

    为避免每次删除后都进行手动更新,您可以在office 表上创建一个AFTER DELETE 触发器,这样每当您从办公室删除一行时表,更新role_map 表。更新语句如下所示:

    UPDATE role_map SET active = 'N' WHERE user_id = :OLD.office_head;
    

    例如,只是一个伪代码

    CREATE OR REPLACE TRIGGER office_trg
    AFTER DELETE
       ON office
       FOR EACH ROW
    
    DECLARE
       -- variable declarations
    
    BEGIN
    
       -- check any conditions if required
    
       UPDATE role_map SET active = 'N' WHERE user_id = :OLD.office_head;
    
    EXCEPTION
       WHEN ...
       -- exception handling
    
    END;
    

    【讨论】:

    • 抱歉打扰了。触发也是我的第一个想法(我在编辑过程中删除了那部分答案),这有点明显,但我害怕ORA-04091: table is mutating。在触发器中,我们必须从必须构造触发器的office 表中进行选择。我知道workarounds,但我怀疑它们对于这个特定问题是否安全/可靠。再一次 - 抱歉打扰了,我想知道。
    • @PonderStibbons 我理解您的担忧,但我完全看不到任何变异错误的可能性。您将根据 office 表的旧删除记录更新 role_map 表。朴素而简单的设计。每次删除后手动执行更新语句不是一个实际的解决方案。所以,我编辑了我的答案,我认为触发器会更合适。
    • 谢谢你们。我接受了 Ponder 提供的答案。但仍然为这个投票。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2017-12-12
    • 2012-01-14
    • 2014-08-01
    • 2013-09-25
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多