0

你好,我有 4 张桌子

第一个表是菜单 有列:

  1. 身份证号PK
  2. parent_id 编号 FK 到 menu.Id
  3. 标题字符变化(250)
  4. softdel 布尔默认值 false

第二个表是页面

  1. 标识为 PK
  2. menu_id 作为 menu.id 的 FK
  3. page_id 作为 page.id 的 FK
  4. softdel 布尔默认值 false

第三张表是文章

  1. id 作为 PK 和 FK 到 page.id
  2. softdel boolean 默认设置为 false

和第四张表article_lang

  1. partial_id 作为 PK
  2. id 作为 article.id 的 FK
  3. 语言字符
  4. softdel boolean 默认设置为 false

当我'删除'(我的意思是设置softdel true)菜单时,我需要创建更新语句,例如200我还将softdel = false设置为所有parent_id = 200的菜单以及所有menu_id = menus_id的页面和page_id的文章= pages.id 等等....

我只需要 1 个更新语句就可以做到吗??

如果我可以创建 JPA 查询或 EJB 查询,那就太好了 :)

在 oracle 我写声明:

update pub_menu pm set softdel = 0 where pm.id in (
with menu_tree(id, parent_id) as (
  select 
    t1.id , t1.parent_id
    from menu t1
    where t1.id = 454

    union all
    select 
    t2.id , t2.parent_id
      from menu_tree
      join menu t2 on menu_tree.id = t2.parent_id
)
select id from menu_tree

)

update menu_page pmp set softdel = 1 where pmp.menu_id in (
with menu_tree(id, parent_id) as (
  select 
    t1.id , t1.parent_id
    from menu t1
    where t1.id = 454

    union all
    select 
    t2.id , t2.parent_id
      from menu_tree
      join menu t2 on menu_tree.id = t2.parent_id
)
select id from menu_tree

)

它的工作,但我这样做是不正确的:/

4

4 回答 4

1

就像是:

with recursive menu_tree (id, parent_id) as (
   select id, parent_id
   from menu
   where id = 200
   union all 
   select c.id, c.parent_id
   from menu c
     join menu_tree p on p.id = c.parent_id
)
, deleted_menus (menu_id) as (
   update menu
      set softdel = true
   where id in (select id from menu_tree)
   returning menu.id
),
deleted_pages (page_id) as (
   update page
      set softdel = true
   where menu_id in (select menu_id from deleted_menus)
   returning page.id
),
deleted_articles (article_id) as (
   update article
     set softdel = true
   where page_id in (select page_id from deleted_pages)
)
update article_lang
   set softdel = true
where id in (select article_id from deleted_articles);
于 2013-02-27T13:55:09.313 回答
0

如果您只是删除它们并让外键级联会更容易。

但是,您可以编写一个简短的触发函数来为您执行额外的删除操作。前 3 个表中的每一个都需要一个,但它们基本相同。他们需要在每个 ROW 的 AFTER 触发器中根据 OLD.id 更新链中的下一个表。

手册中的触发功能示例。

于 2013-02-27T13:49:25.917 回答
0

您可以将多个更新与 CTE 结合起来:

WITH u1 AS (UPDATE menu SET softdel = TRUE WHERE menu.id = 200),
     u2 AS (UPDATE menu SET softdel = FALSE WHERE menu.parent_id = 200),
     u3 AS (...),
     u4 AS (...),
     -- and so on
SELECT 1
于 2013-02-27T13:53:52.113 回答
0

Oracle 不允许任何一条 sql 语句更新多个表。因此,在这种情况下,常规 CTE 无法避免代码重复。

但这可以通过使用PL/SQL FOR LOOP IMPLICIT CURSOR来解决,如下所示:

begin
  for cur in (
    with menu_tree(id, parent_id) as (
        select t1.id, t1.parent_id
        from menu t1 where t1.id = 454
        union all
        select t2.id , t2.parent_id
        from menu_tree
        join menu t2 on menu_tree.id = t2.parent_id
    )
    select id from menu_tree
  ) loop
    update pub_menu pm set softdel = 0 where pm.id = cur.id;
    update menu_page pmp set softdel = 1 where pmp.menu_id = cur.id;
  end loop cur;
end;
于 2017-11-16T17:18:58.840 回答