oracle ddl 触发器:在删除之前创建备份 table
oracle ddl trigger: create backup table with before drop
我想使用 ddl 触发器(删除前)创建备份 table,但遇到了以下问题。
第一次丢弃时没关系:a_backup table 包含丢弃的数据 table。但是为什么我不能在这之后删除另一个 table?
ORA-01031: insufficient privileges
create table b (x number);
-- Table B created.
create table a (x number);
-- Table A created.
create table a_backup as select * from a where 1 = 0;
-- Table A_BACKUP created.
create or replace trigger a_backup_tr
before drop
on database
begin
IF ora_dict_obj_name <> 'A' then
null;
ELSIF ora_dict_obj_name = 'A'
and ora_dict_obj_owner = 'TRANEE' then
insert into a_backup
select * from a;
ELSE null;
end if;
end;
/
-- Trigger A_BACKUP_TR compiled
-- 1
drop table a;
-- Table A dropped.
-- 2
drop table b;
-- ORA-04045: errors during recompilation/revalidation of TRANEE.A_BACKUP_TR
-- ORA-01031: insufficient privileges
并且您不能在删除后删除任何 table,除非您再次运行创建或替换触发器脚本。 IF-THEN 部分有问题吗?当 table A 不存在时,IF 语句必须进入 NULL?
But why I cannot drop another table after this?
insert into a_backup select * from a;
在触发器中,您明确引用了 table A,但当时它不存在。
你可以使用动态 SQL:
create or replace trigger a_backup_tr
before drop
on database
begin
IF ora_dict_obj_name <> 'A' then
null;
ELSIF ora_dict_obj_name = 'A' and ora_dict_obj_owner = 'TRANEE' then
EXECUTE IMMEDIATE 'insert into tranee.a_backup select * from tranee.a';
ELSE null;
end if;
end;
/
就我个人而言,我不喜欢为这种机制使用触发器的想法。如果模式在未来漂移,盲插入和 SELECT *
也可能会失败。也许更好的方法是 Flashback Drop (Recycle Bin)
编辑:
如@wolφi 所述,为了减少盲插入,您可以在触发器内创建 table:
create or replace trigger a_backup_tr
before drop
on database
begin
IF ora_dict_obj_name <> 'A' then
null;
ELSIF ora_dict_obj_name = 'A' and ora_dict_obj_owner = 'TRANEE' then
--TODO: additional check if table already exists
EXECUTE IMMEDIATE 'CREATE TABLE tranee.a_backup AS SELECT * FROM tranee.a';
ELSE null;
end if;
end;
/
我想使用 ddl 触发器(删除前)创建备份 table,但遇到了以下问题。
第一次丢弃时没关系:a_backup table 包含丢弃的数据 table。但是为什么我不能在这之后删除另一个 table?
ORA-01031: insufficient privileges
create table b (x number);
-- Table B created.
create table a (x number);
-- Table A created.
create table a_backup as select * from a where 1 = 0;
-- Table A_BACKUP created.
create or replace trigger a_backup_tr
before drop
on database
begin
IF ora_dict_obj_name <> 'A' then
null;
ELSIF ora_dict_obj_name = 'A'
and ora_dict_obj_owner = 'TRANEE' then
insert into a_backup
select * from a;
ELSE null;
end if;
end;
/
-- Trigger A_BACKUP_TR compiled
-- 1
drop table a;
-- Table A dropped.
-- 2
drop table b;
-- ORA-04045: errors during recompilation/revalidation of TRANEE.A_BACKUP_TR
-- ORA-01031: insufficient privileges
并且您不能在删除后删除任何 table,除非您再次运行创建或替换触发器脚本。 IF-THEN 部分有问题吗?当 table A 不存在时,IF 语句必须进入 NULL?
But why I cannot drop another table after this?
insert into a_backup select * from a;
在触发器中,您明确引用了 table A,但当时它不存在。
你可以使用动态 SQL:
create or replace trigger a_backup_tr
before drop
on database
begin
IF ora_dict_obj_name <> 'A' then
null;
ELSIF ora_dict_obj_name = 'A' and ora_dict_obj_owner = 'TRANEE' then
EXECUTE IMMEDIATE 'insert into tranee.a_backup select * from tranee.a';
ELSE null;
end if;
end;
/
就我个人而言,我不喜欢为这种机制使用触发器的想法。如果模式在未来漂移,盲插入和 SELECT *
也可能会失败。也许更好的方法是 Flashback Drop (Recycle Bin)
编辑:
如@wolφi 所述,为了减少盲插入,您可以在触发器内创建 table:
create or replace trigger a_backup_tr
before drop
on database
begin
IF ora_dict_obj_name <> 'A' then
null;
ELSIF ora_dict_obj_name = 'A' and ora_dict_obj_owner = 'TRANEE' then
--TODO: additional check if table already exists
EXECUTE IMMEDIATE 'CREATE TABLE tranee.a_backup AS SELECT * FROM tranee.a';
ELSE null;
end if;
end;
/