Oracle рдореЗрдВ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдорд░реНрдЬ

рдХреБрдЫ рджрд┐рди рдкрд╣рд▓реЗ, рдореИрдВрдиреЗ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрд╕реАрдХреНрдпреВрдПрд▓ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ ред рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛ рджреВрдВ рдХрд┐ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕реЗ рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ рдмрд╛рд░-рдмрд╛рд░ рдХреА рдЧрдИ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЧрд▓рддреА рд╕реЗред рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдирд┐рдХрд▓рд╛, рдУрд░реЗрдХрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╛рди рдЙрдкрдХрд░рдг рднреА рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдбрд┐рдмрдЧрд┐рдВрдЧ рдФрд░ рд╣рдорд╛рд░реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ "рд╕рдВрджрд░реНрдн" рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВрдЧреЗ:

рдЫрд╡рд┐

рдЯреЗрд╕реНрдЯ рдЯреЗрдмрд▓
create table city ( id number not null, name varchar2(30) not null ); create unique index city_pk on city(id); alter table city add constraint city_pk primary key(id); create table street ( id number not null, city_id number not null, name varchar2(30) not null ); create unique index street_pk on street(id); create index street_fk on street(city_id); alter table street add constraint street_pk primary key(id); alter table street add constraint fk_street foreign key (city_id) references city(id); create table address ( id number not null, street_id number not null, house varchar2(10) not null, apartment varchar2(10) ); create unique index address_pk on address(id); create index address_fk on address(street_id); alter table address add constraint address_pk primary key(id); alter table address add constraint fk_address foreign key (street_id) references street(id); 


... рдФрд░ рдЙрдиреНрд╣реЗрдВ рдбреЗрдЯрд╛ рд╕реЗ рднрд░реЗрдВ:

рдбреЗрдЯрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ
 insert into city(id, name) values (1, ''); insert into street(id, city_id, name) values (1, 1, ''); insert into street(id, city_id, name) values (2, 1, ' '); insert into address(id, street_id, house, apartment) values (1, 1, '10', '1'); insert into address(id, street_id, house, apartment) values (2, 2, '10', '2'); 


рдЕрдм рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЛ "рдорд░реНрдЬ" рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ? рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо "рдбреБрдкреНрд▓рд┐рдХреЗрдЯ" рдорд╛рдирддреЗ рд╣реИрдВред рдпрд╣ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рднреА рд▓рд┐рдВрдХ рдХреЛ рдмрджрд▓ рджреЗрдВ рддрд╛рдХрд┐ рд╡реЗ рджреВрд╕рд░реЗ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВред рдмреЗрд╢рдХ, рдпрд╣ рд╕рдм рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпрд╣ рдХреНрд░рд┐рдпрд╛, рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рд╡рд╛рдкрд╕ рд▓реЗ рдЬрд╛ рд╕рдХреЗред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╕реЗрд╡рд╛ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ рд░реЛрд▓рдмреИрдХ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА рд░рд┐рдХреЙрд░реНрдб рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ:

рдЫрд╡рд┐

рд╕реЗрд╡рд╛ рддрд╛рд▓рд┐рдХрд╛рдУрдВ
 create table mg_table ( name varchar2(30) not null ); create unique index mg_table_pk on mg_table(name); alter table mg_table add constraint mg_table_pk primary key(name); create sequence mg_merge_seq; create table mg_merge ( id number not null, table_name varchar2(30) not null, old_id number not null, new_id number not null ); create unique index mg_merge_pk on mg_merge(id); create unique index mg_merge_uk on mg_merge(table_name, old_id); alter table mg_merge add constraint mg_merge_pk primary key(id); alter table mg_merge add constraint fk_mg_merge foreign key (table_name) references mg_table(name); create sequence mg_ref_seq; create table mg_ref ( id number not null, merge_id number not null, table_name varchar2(30) not null, pk_name varchar2(30) not null, column_name varchar2(30) not null, object_id number not null ); create unique index mg_ref_pk on mg_ref(id); create index mg_ref_fk on mg_ref(merge_id); alter table mg_ref add constraint mg_ref_pk primary key(id); alter table mg_ref add constraint fk_mg_ref foreign key (merge_id) references mg_merge(id); 


рд╣рдЯрд╛рдП рдЧрдП рд░рд┐рдХреЙрд░реНрдб рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдореВрд▓ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рджреЛрд╣рд░рд╛рддреА рд╣реИред рдпрд╣ рддрд╛рд▓рд┐рдХрд╛ рд╕рдВрдмрдВрдзрд┐рдд рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЗ рдкрд╣рд▓реЗ рдорд░реНрдЬ рдХреЗ рджреМрд░рд╛рди рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдмрдирд╛рдИ рдЬрд╛рдПрдЧреАред рд╣рдо рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдирд╛рдо рдХреЗ рд▓рд┐рдП рдЙрдкрд╕рд░реНрдЧ "mg_" рдЬреЛрдбрд╝рдХрд░ рдирд╛рдо рдмрдирд╛рдПрдВрдЧреЗ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдкрд╣рд▓реА рдмрд╛рд░ рд╣рдореЗрдВ рд╕рдбрд╝рдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдорд░реНрдЬ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╣рдЯрд╛рдП рдЧрдП рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП mg_street рддрд╛рд▓рд┐рдХрд╛ рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛)ред

рддрд╛рд▓рд┐рдХрд╛ mg_table рдЗрд╕ рддрд░рд╣ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЗ рдирд╛рдо рджрд░реНрдЬ рдХрд░реЗрдЧрд╛ред Mg_merge рдореЗрдВ рд╣рдо рдорд░реНрдЬ рдХрд┐рдП рдЧрдП рд░рд┐рдХреЙрд░реНрдб рдХреА рдХреБрдВрдЬрд┐рдпрд╛рдБ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗ, рдФрд░ mg_ref рдореЗрдВ рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдХреЗ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдЬреЛ рдкреБрд░рд╛рдиреЗ рдореВрд▓реНрдп рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдиреЛрдЯрд┐рд╕ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ рдХрд┐ рд▓реБрдХрдЕрдк рдЯреЗрдмрд▓ рдХреА рдРрд╕реА рд╕рдВрд░рдЪрдирд╛ рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдПрдХрд▓-рд╕реНрддрдВрдн рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ, рдкрд╣рд▓реА рдЪреАрдЬрд╝ рдЬреЛ рд╣рдореЗрдВ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╣рдо рдЪрдпрдирд┐рдд рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 select max(cn) from ( select b.constraint_name, count(*) cn from user_constraints a inner join user_constraints b on (b.r_constraint_name = a.constraint_name) inner join user_cons_columns c on (c.constraint_name = b.constraint_name) where a.table_name = upper(p_name) group by b.constraint_name ); 

рдЗрд╕ рдкреНрд░рд╢реНрди рдХреЗ рд╕рд╛рде, рд╣рдо рд╡рд┐рджреЗрд╢реА рдХреБрдВрдЬрд┐рдпреЛрдВ рдореЗрдВ рдЕрдзрд┐рдХрддрдо рдХреЙрд▓рдо рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ p_name рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рд╕рдВрджрд░реНрдн рджреЗрддреЗ рд╣реИрдВред рдпрд╣ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдУрд░реЗрдХрд▓ рдореЗрдВ рдРрд╕реЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рд╕рдВрдХрд▓рди рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред рд╕рднреА рдУрд░реЗрдХрд▓ рд╕рд┐рд╕реНрдЯрдо рдЕрднреНрдпрд╛рд╡реЗрджрди рдХреЗ рдирд╛рдо рдХреЛ рдпрд╛рдж рд░рдЦрдирд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд░рд▓ рдЕрдиреБрд░реЛрдз рдХреЛ рдЪрд▓рд╛рдХрд░ рд╣рдореЗрд╢рд╛ рдЕрдкрдиреА рд╕реНрдореГрддрд┐ рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 select * from dictionary 

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдорд░реНрдЬ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд╕рднреА рдЪрд░рдг рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЙрдиреНрд╣реЗрдВ рддрддреНрдХрд╛рд▓ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рдХреНрд░рд┐рдп рдЙрдкрдпреЛрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдкреИрдХреЗрдЬ рдХрд╛ рдкреВрд░реНрдг рд╕реНрд░реЛрдд рдХреЛрдб рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рдореЗрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ)ред

рд░реЛрд▓рдмреИрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд░ рдХреБрдЫ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдВрддрд┐рдо рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рд╡рд╛рдкрд╕ рд░реЛрд▓ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд░реНрдгрд┐рдд рдкреИрдХреЗрдЬ рдЖрдкрдХреЛ рдЗрд╕рдХреА рдЖрдИрдбреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдХреЗ рдПрдХ рднреА рдкрд░рд┐рд╡рд░реНрддрди рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдХрд┐рд╕реА рднреА рдорд░реНрдЬ рдХреЛ рдЗрд╕ рддрд░рд╣ рд╡рд╛рдкрд╕ рдирд╣реАрдВ рд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд╡реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рд░реЛрд▓рдмреИрдХ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреА рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИ:

 select count(*) from mg_merge where old_id = l_new; 

рдЗрд╕ рдЪреЗрдХ рдХрд╛ рдЕрд░реНрде рд╕рд░рд▓ рд╣реИ - рд╣рдо рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдХреЗ рдорд░реНрдЬ рдХреЛ рд╡рд╛рдкрд╕ рдирд╣реАрдВ рд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдмрд╛рдж рд╢реЗрд╖ рд░рд┐рдХреЙрд░реНрдб рдмрд╛рдж рдореЗрдВ рдХрд┐рд╕реА рдЕрдиреНрдп рдорд░реНрдЬ рджреНрд╡рд╛рд░рд╛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛред

рдкреИрдХреЗрдЬ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИ:

mg_merge_pkg.sql
 create or replace package mg_merge_pkg as procedure merge(p_name in varchar2, p_old in number, p_new in number); procedure undo(p_id in number); procedure undo; end mg_merge_pkg; / show errors; create or replace package body mg_merge_pkg as e_unsupported_error EXCEPTION; pragma EXCEPTION_INIT(e_unsupported_error, -20001); cursor c_col(p_name varchar2, p_pk varchar2) is select column_name from user_tab_columns where table_name = upper(p_name) and column_name <> p_pk; procedure merge(p_name in varchar2, p_old in number, p_new in number) as cursor c_fk is select b.table_name, c.column_name, e.column_name pk_name from user_constraints a inner join user_constraints b on (b.r_constraint_name = a.constraint_name) inner join user_cons_columns c on (c.constraint_name = b.constraint_name) inner join user_constraints d on (d.table_name = b.table_name and d.constraint_type = 'P') inner join user_cons_columns e on (e.constraint_name = d.constraint_name) where a.table_name = upper(p_name); r_fk c_fk%rowtype; r_col c_col%rowtype; l_id number default null; l_cn number default null; l_pk varchar2(30) default null; l_sql varchar2(500) default null; begin select max(cn) into l_cn from ( select b.constraint_name, count(*) cn from user_constraints a inner join user_constraints b on (b.r_constraint_name = a.constraint_name) inner join user_cons_columns c on (c.constraint_name = b.constraint_name) where a.table_name = upper(p_name) group by b.constraint_name ); if l_cn > 1 then RAISE_APPLICATION_ERROR(-20001, 'Can''t support multicolumn FK'); end if; select c.column_name into l_pk from user_constraints a inner join user_cons_columns c on (c.constraint_name = a.constraint_name) where a.table_name = upper(p_name) and a.constraint_type = 'P'; select count(*) into l_cn from mg_table where name = upper(p_name); if l_cn = 0 then insert into mg_table(name) values (upper(p_name)); execute immediate 'create table mg_' || p_name || ' as select * from ' || upper(p_name) || ' ' || 'where rownum = 0'; execute immediate 'create unique index mg_' || p_name || '_pk on mg_' || p_name || '(' || l_pk || ')'; end if; insert into mg_merge(id, table_name, old_id, new_id) values (mg_merge_seq.nextval, upper(p_name), p_old, p_new) returning id into l_id; open c_fk; loop fetch c_fk into r_fk; exit when c_fk%notfound; execute immediate 'insert into mg_ref(id, merge_id, table_name, pk_name, column_name, object_id) ' || 'select mg_ref_seq.nextval, :merge_id, :tab_name, :pk_name, :col_name, ' || r_fk.pk_name || ' ' || 'from ' || r_fk.table_name || ' where ' || r_fk.column_name || ' = :old_id' using l_id, r_fk.table_name, r_fk.pk_name, r_fk.column_name, p_old; execute immediate 'update ' || r_fk.table_name || ' set ' || r_fk.column_name || ' = :new_id ' || 'where ' || r_fk.column_name || ' = :old_id' using p_new, p_old; end loop; close c_fk; l_sql := 'insert into mg_' || p_name || '(' || l_pk; open c_col(p_name, l_pk); loop fetch c_col into r_col; exit when c_col%notfound; l_sql := l_sql || ',' || r_col.column_name; end loop; close c_col; l_sql := l_sql || ') select '|| l_pk; open c_col(p_name, l_pk); loop fetch c_col into r_col; exit when c_col%notfound; l_sql := l_sql || ',' || r_col.column_name; end loop; close c_col; l_sql := l_sql || ' from ' || p_name || ' where ' || l_pk || ' = :old_id'; execute immediate l_sql using p_old; execute immediate 'delete from ' || p_name || ' where ' || l_pk || ' = :id' using p_old; commit; exception when others then if c_fk%isopen then close c_fk; end if; if c_col%isopen then close c_col; end if; rollback; raise; end; procedure undo(p_id in number) as cursor c_fk is select table_name, pk_name, column_name from mg_ref where merge_id = p_id group by table_name, pk_name, column_name; r_fk c_fk%rowtype; r_col c_col%rowtype; l_name varchar2(30) default null; l_old number default null; l_new number default null; l_cn number default null; l_pk varchar2(30) default null; l_sql varchar2(500) default null; begin select table_name, old_id, new_id into l_name, l_old, l_new from mg_merge where id = p_id; select count(*) into l_cn from mg_merge where old_id = l_new; if l_cn > 0 then RAISE_APPLICATION_ERROR(-20001, 'Can''t undo'); end if; select c.column_name into l_pk from user_constraints a inner join user_cons_columns c on (c.constraint_name = a.constraint_name) where a.table_name = upper(l_name) and a.constraint_type = 'P'; l_sql := 'insert into ' || l_name || '(' || l_pk; open c_col(l_name, l_pk); loop fetch c_col into r_col; exit when c_col%notfound; l_sql := l_sql || ',' || r_col.column_name; end loop; close c_col; l_sql := l_sql || ') select '|| l_pk; open c_col(l_name, l_pk); loop fetch c_col into r_col; exit when c_col%notfound; l_sql := l_sql || ',' || r_col.column_name; end loop; close c_col; l_sql := l_sql || ' from mg_' || l_name || ' where ' || l_pk || ' = :old_id'; execute immediate l_sql using l_old; open c_fk; loop fetch c_fk into r_fk; exit when c_fk%notfound; execute immediate 'merge into ' || r_fk.table_name || ' d using mg_ref s '|| 'on (s.object_id = d.' || r_fk.pk_name || ' and s.merge_id = :id and s.table_name = :tab_name and s.column_name = :col_name) ' || 'when matched then ' || 'update set d.' || r_fk.column_name || ' = :old_id' using p_id, r_fk.table_name, r_fk.column_name, l_old; end loop; close c_fk; execute immediate 'delete from mg_' || l_name || ' where ' || l_pk || ' = :id' using l_old; delete from mg_ref where merge_id = p_id; delete from mg_merge where id = p_id; commit; exception when others then if c_fk%isopen then close c_fk; end if; if c_col%isopen then close c_col; end if; rollback; raise; end; procedure undo as l_id number default null; begin select max(id) into l_id from mg_merge; undo(l_id); end; end mg_merge_pkg; / show errors; 


рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд╡реЗрд░реА рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдХреЗ рд╢рдмреНрджрдХреЛрд╢ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдорд░реНрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 begin mg_merge_pkg.merge('street', 2, 1); end; 


рдФрд░ рд░реЛрд▓ рдмреИрдХ рдЕрдиреБрд░реЛрдз рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░реЗрдВ:

 begin mg_merge_pkg.undo; end; 

Source: https://habr.com/ru/post/In181378/


All Articles