PLSQL合并 - 更新,而行不存在

问题描述:

我有三个表用户,办公室和角色图。用户标识将成为Office办公室经理和办公室主管的FK。角色和用户ID将被映射到角色映射表中,如下所示。 删除某个办公室时,办公室表的活动列将更新为'N'。 办公室被删除时,我必须检查办公室经理是否作为其他办公室的办公室经理。 (同样的人可以是经理,另一个市场太) 如果他不是,那我也通过更新活动标志以“N”PLSQL合并 - 更新,而行不存在

表用户删除的角色映射表中的条目

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  | 

所以在THI例如,如果删除Office 2,则需要将角色映射表中的第三个条目更新为以下 OFfice管理器角色映射将完好无损,因为同一个用户也是Off1的管理器。

角色映射 - 更新

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

    2 | Office Head  | Y  | 

    4 | Office Head  | N  | 

我不能确定如何实现在PL/SQL此查询后。有人可以在这里指导我吗?

+0

我认为MERGE不会在这里很有用。我会创建一个触发器,以避免每次删除后手动更新。 – 2015-04-06 15:16:41

我认为在这种情况下不使用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根本不知道,或许它可以用视图代替,但也许你储存一些其他数据。

+0

谢谢。这是我试图编写的查询。 – nprak 2015-04-07 09:20:35

如果您已经从Office表中删除的行,你可以只检查是否存在在办公台上的员工有积极的作用或没有,只是做一个简单的更新这样的 -

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

PLSQL合并 - 更新,而第一行不存在

我不认为你可以使用做一个UPDATE当在MERGE语句 NOT MATCHED

为了避免每次都做手动更新删除后,你可以在office表后删除触发器创建这样,每当你从办公室表中删除一行,更新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; 
+0

对不起,打扰你了。触发是我的第一个想法(我在编辑过程中删除了这部分答案),这很明显,但我害怕ORA-04091:表格在变化。 在触发器中,我们必须从“办公室”表中选择哪个触发器必须构建。 我知道[解决方法](https://decipherinfosys.wordpress.com/2009/06/22/mutating-tabletrigger-error-and-how-to-resolve-it/), 但我怀疑他们是安全的/可靠的这个特定的问题。再次 - 抱歉,我很想知道。 – 2015-04-06 23:18:13

+0

@PonderStibbons我理解你的担忧,但我根本没有看到有任何变异错误的可能性。您将根据Office表的旧删除记录更新role_map表。简单和简单的设计。每次删除后手动执行更新语句都不是一个实际的解决方案。所以,我编辑了我的答案,我认为触发会更合适。 – 2015-04-07 03:45:00

+0

谢谢你们。我接受了思考提供的答案。但仍然投票支持这一个。再次感谢。 – nprak 2015-04-07 09:22:03