インラインビューの更新

 

MySQLPostgreSQLSQL Serverはインラインビューの更新不可

(8.0.29)

drop table tab1;
create table tab1(
    col1 bigint primary key
   ,col2 bigint
   );

drop table tab2;
create table tab2(
    col1 bigint primary key
   ,col2 bigint
   );

 

drop procedure proc1;

delimiter //
create procedure proc1(in x int)
begin
  declare i int;
  set i = 0;
  start transaction;
  while i < x do
    set i = i + 1;
    insert into tab1 values(
     i
    ,1
    );
    insert into tab2 values(
     i
    ,2
    );
  end while;
  commit;
end
//
delimiter ;

call proc1(100000);

analyze table tab1;
analyze table tab2;

 

[1]インラインビュー

update ( 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
) t0
set t0.col12 = t0.col22
;

→ ERROR 1288 (HY000): The target table t0 of the UPDATE is not updatable ★

 


[2]複数テーブル構文

※一致した各行は、条件に複数回一致した場合でも、1 回更新されます。


update tab1 t1,tab2 t2
set t1.col2 = t2.col2
where t1.col1 = t2.col1
;

→更新可能


[3]通常ビュー

drop view view1;
create view view1 as 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
;

update view1 t0
set t0.col12 = t0.col22
;

→更新可能

 

[4]サブクエリ

update tab1 t1
set t1.col2 = ( select col2 from tab2 t2 where  t2.col1 = t1.col1)
;

→更新可能

 

 

 

(19c)

drop table tab1 purge;
create table tab1(
    col1 int constraint tab1pk primary key
   ,col2 int
  );

drop table tab2 purge;
create table tab2(
    col1 int constraint tab2pk primary key
   ,col2 int
   );


declare
begin
for i in 1..100000 loop
  insert into tab1 values(
    i
   ,1
   );
  insert into tab2 values(
    i
   ,2
   );

end loop;
end;
/

commit;
set time on
set timing on

exec dbms_stats.gather_table_stats(user,'TAB1');
exec dbms_stats.gather_table_stats(user,'TAB2');

[1]インラインビュー

explain plan for
update ( 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
) t0
set t0.col12 = t0.col22
;

select * from table(dbms_xplan.display(format=>'ALL') );

→更新可能。実行計画はHJ

[2]通常ビュー

drop view view1;
create view view1 as 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
;

explain plan for
update view1 t0
set t0.col12 = t0.col22
;

select * from table(dbms_xplan.display(format=>'ALL') );


→更新可能。実行計画はHJ


[3]サブクエリ

explain plan for
update tab1 t1
set t1.col2 = ( select col2 from tab2 t2 where  t2.col1 = t1.col1)
;

select * from table(dbms_xplan.display(format=>'ALL') );


→更新可能。実行計画はNL模様

 

 


(14)

drop table tab1 cascade;
create table tab1(
    col1 bigint constraint tab1pk primary key
   ,col2 bigint
  );
drop table tab2 cascade;
create table tab2(
    col1 bigint constraint tab2pk primary key
   ,col2 bigint
   );

 


start transaction;
insert into tab1 select
   g
  ,1
from generate_series(1,100000) g;

commit;

start transaction;
insert into tab2 select
   g
  ,2
from generate_series(1,100000) g;

commit;


\timing 1
\pset pager 0

 

analyze tab1;
analyze tab2;


[1]インラインビュー

update ( 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
) t0
set t0.col12 = t0.col22
;


→ ERROR:  syntax error at or near "(" ★


[2]update from構文

update tab1 t1
set col2 = t2.col2
from tab2 t2
where t1.col1 = t2.col1
;

→更新可能

 

[3]通常ビュー

drop view view1;
create view view1 as 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
;

update view1 t0
set col12 = t0.col22
;

ERROR:  cannot update view "view1" ★
DETAIL:  Views that do not select from a single table or view are not automatically updatable.
HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.

 


[4]サブクエリ


update tab1 t1
set col2 = ( select col2 from tab2 t2 where  t2.col1 = t1.col1)
;

→更新可能


※set句のcol2をt1別名修飾するとエラーとなる

 

 

(2019)


drop table tab1;
create table tab1(
    col1 bigint not null constraint tab1pk primary key
   ,col2 bigint
   );

drop table tab2;
create table tab2(
    col1 bigint not null  constraint tab2pk primary key
   ,col2 bigint
   );


set nocount on
declare @i int;
set @i = 1;
begin transaction;
while @i <= 100000
begin
   insert into tab1 values(
     @i
    ,1
    );
   insert into tab2 values(
     @i
    ,2
    );
 set @i = @i + 1;
end
commit;


update statistics tab1;
update statistics tab2;

set statistics time on

 

[1]インラインビュー


update ( 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1

set col12 = t0.col22
;

→ '(' 付近に不適切な構文があります。 ★

 

[2]update from構文

update t1
set t1.col2 = t2.col2
from tab1 t1,tab2 t2
where t1.col1 = t2.col1
;

→更新可能


[3]通常ビュー


drop view view1;
go

create view view1 as 
select 
  t1.col1 col11
 ,t1.col2 col12
 ,t2.col2 col22
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
;
go

update view1 
set col12 = col22
;

→更新可能

※テーブル名や列名を修飾するとエラーとなる

 

[4]サブクエリ

update tab1 
set col2 = ( select col2 from tab2 t2 where  t2.col1 = tab1.col1)
;

→更新可能