Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
oracle ddl触发器:在删除之前使用创建备份表_Oracle_Plsql_Triggers_Ddl Trigger - Fatal编程技术网

oracle ddl触发器:在删除之前使用创建备份表

oracle ddl触发器:在删除之前使用创建备份表,oracle,plsql,triggers,ddl-trigger,Oracle,Plsql,Triggers,Ddl Trigger,我想在drop之前使用ddl触发器创建一个备份表,但遇到了以下问题 当第一次删除发生时,一切正常:a_备份表包含被删除表的数据。但是为什么我不能在这之后放下另一张桌子呢 ORA-01031:权限不足 -创建了表B -表A已创建 -表A\u已创建备份 -桌子A掉了 -ORA-04045:TRANEE.A\u BACKUP\u TR重新编译/重新验证期间的错误 -ORA-01031:权限不足 除再次运行创建或替换触发器脚本外,您不能在删除后删除任何表。IF-THEN部件有问题吗?当表A不存在时,IF

我想在drop之前使用ddl触发器创建一个备份表,但遇到了以下问题

当第一次删除发生时,一切正常:a_备份表包含被删除表的数据。但是为什么我不能在这之后放下另一张桌子呢

ORA-01031:权限不足

-创建了表B

-表A已创建

-表A\u已创建备份

-桌子A掉了

-ORA-04045:TRANEE.A\u BACKUP\u TR重新编译/重新验证期间的错误

-ORA-01031:权限不足

除再次运行创建或替换触发器脚本外,您不能在删除后删除任何表。IF-THEN部件有问题吗?当表A不存在时,IF语句必须变为NULL

但是为什么我不能在这之后放下另一张桌子呢

在触发器中,您显式地引用了表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;
/
但是为什么我不能在这之后放下另一张桌子呢

在触发器中,您显式地引用了表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;
/

是否需要在ON数据库触发器中限定_备份的架构?@wolφi它将按原样工作。但明确限定名称是个好主意。好的,谢谢@迪波尔:我同意卢卡斯的观点,在触发器中备份可能不是一个好主意。如果有的话,我会在触发器主体中使用CREATE TABLE tranee.a_backup作为SELECT*FROM tranee.a,而不是INSERT。它更快,无需撤销,更安全,在一个地方没有列和更干净的代码问题。谢谢您的编辑,非常感谢!“重命名”是否也会起作用,还是会弄乱DROP语句?而且,仔细想想,这正是回收蛋白所做的,不是吗?@wolφi是的,这项技术被称为。至于重命名,则不会触发drop触发器。是否需要在ON数据库触发器中限定_备份的架构?@wolφi它将按原样工作。但明确限定名称是个好主意。好的,谢谢@迪波尔:我同意卢卡斯的观点,在触发器中备份可能不是一个好主意。如果有的话,我会在触发器主体中使用CREATE TABLE tranee.a_backup作为SELECT*FROM tranee.a,而不是INSERT。它更快,无需撤销,更安全,在一个地方没有列和更干净的代码问题。谢谢您的编辑,非常感谢!“重命名”是否也会起作用,还是会弄乱DROP语句?而且,仔细想想,这正是回收蛋白所做的,不是吗?@wolφi是的,这项技术被称为。至于重命名,它不会触发删除。只是注意到您在问题中开发的功能与Oracle的功能非常相似。只是注意到您在问题中开发的功能与Oracle的功能非常相似。
create table a_backup as select * from a where 1 = 0;
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;
/
-- 1

drop table a;
-- 2

drop table b;
insert into a_backup select * from a; 
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;
/
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;
/