SQL 使用先验连接更新查询的语法
SQL syntax for update query with connect by prior
我开始使用 SQL 并面临分层查询。同时,我使用 connect by prior
命令成功 select 行,但未能更新。这是我的更新查询:
update HTABLE set status = 'INACTIVE'
WHERE STATUS <> 'CLOSE'
Connect by prior PARENT_ID=ID start with PARENT_ID=12345;
我得到了SQL Error: ORA-00933: SQL command not properly ended
。如何分层更新 table?
编辑
我也试过把where
条件放在start with
里,但是没用:
update HTABLE set status = 'INACTIVE'
Connect by prior PARENT_ID=ID start with PARENT_ID=12345 AND STATUS <> 'CLOSE';
您可以使用子句 where id in (select ... connect by...)
进行更新,也可以使用 merge
:
merge into htable h
using (select distinct id
from htable
where status <> 'CLOSE'
connect by prior parent_id = id
start with parent_id = 11) src
on (h.id = src.id)
when matched then update set status = 'INACTIVE'
测试数据:
create table htable (id number(4), parent_id number(4), status varchar2(10));
insert into htable values ( 1, null, 'ACTIVE');
insert into htable values ( 11, 1, 'CLOSE');
insert into htable values ( 12, 1, 'ACTIVE');
insert into htable values ( 111, 11, 'ACTIVE');
insert into htable values ( 112, 11, 'ACTIVE');
insert into htable values ( 121, 12, 'ACTIVE');
insert into htable values ( 2, null, 'ACTIVE');
insert into htable values ( 21, 2, 'ACTIVE');
insert into htable values ( 211, 21, 'ACTIVE');
insert into htable values ( 212, 21, 'ACTIVE');
和merge
之后:
ID PARENT_ID STATUS
----- --------- ----------
1 INACTIVE
11 1 INACTIVE
12 1 ACTIVE
111 11 INACTIVE
112 11 INACTIVE
121 12 ACTIVE
2 ACTIVE
21 2 ACTIVE
211 21 ACTIVE
212 21 ACTIVE
分层查询仅适用于 SELECT。它不适用于 UPDATE(我同意如果可以的话它会很整洁)。
所以你可以做的是:
update HTABLE
set status = 'INACTIVE'
WHERE STATUS <> 'CLOSE'
and id in ( select c.id
from htable
connect by prior ID = PARENT_ID
start with PARENT_ID = 12345);
注意列的顺序 connect by prior ID = PARENT_ID
。通常我们想从 START WITH 行沿着树向下走,这就是我所做的。您的排序 connect by prior PARENT_ID = ID
从 12345 沿着树向上移动到它的 parents、grandparents 等。如果这是您想要的,请将 connect by
子句切换回来。
我开始使用 SQL 并面临分层查询。同时,我使用 connect by prior
命令成功 select 行,但未能更新。这是我的更新查询:
update HTABLE set status = 'INACTIVE'
WHERE STATUS <> 'CLOSE'
Connect by prior PARENT_ID=ID start with PARENT_ID=12345;
我得到了SQL Error: ORA-00933: SQL command not properly ended
。如何分层更新 table?
编辑
我也试过把where
条件放在start with
里,但是没用:
update HTABLE set status = 'INACTIVE'
Connect by prior PARENT_ID=ID start with PARENT_ID=12345 AND STATUS <> 'CLOSE';
您可以使用子句 where id in (select ... connect by...)
进行更新,也可以使用 merge
:
merge into htable h
using (select distinct id
from htable
where status <> 'CLOSE'
connect by prior parent_id = id
start with parent_id = 11) src
on (h.id = src.id)
when matched then update set status = 'INACTIVE'
测试数据:
create table htable (id number(4), parent_id number(4), status varchar2(10));
insert into htable values ( 1, null, 'ACTIVE');
insert into htable values ( 11, 1, 'CLOSE');
insert into htable values ( 12, 1, 'ACTIVE');
insert into htable values ( 111, 11, 'ACTIVE');
insert into htable values ( 112, 11, 'ACTIVE');
insert into htable values ( 121, 12, 'ACTIVE');
insert into htable values ( 2, null, 'ACTIVE');
insert into htable values ( 21, 2, 'ACTIVE');
insert into htable values ( 211, 21, 'ACTIVE');
insert into htable values ( 212, 21, 'ACTIVE');
和merge
之后:
ID PARENT_ID STATUS
----- --------- ----------
1 INACTIVE
11 1 INACTIVE
12 1 ACTIVE
111 11 INACTIVE
112 11 INACTIVE
121 12 ACTIVE
2 ACTIVE
21 2 ACTIVE
211 21 ACTIVE
212 21 ACTIVE
分层查询仅适用于 SELECT。它不适用于 UPDATE(我同意如果可以的话它会很整洁)。
所以你可以做的是:
update HTABLE
set status = 'INACTIVE'
WHERE STATUS <> 'CLOSE'
and id in ( select c.id
from htable
connect by prior ID = PARENT_ID
start with PARENT_ID = 12345);
注意列的顺序 connect by prior ID = PARENT_ID
。通常我们想从 START WITH 行沿着树向下走,这就是我所做的。您的排序 connect by prior PARENT_ID = ID
从 12345 沿着树向上移动到它的 parents、grandparents 等。如果这是您想要的,请将 connect by
子句切换回来。