alter table a drop cascade constraint

解决方案 »

  1.   

    我感觉这样不行!删掉级联关系之后,那如果主表中的ID 改变,而子表中没有改变,那子表不就找不着父表了?如果有级联关系,就改不了了,怎么办呢?做一个触发器,我对sql 语法不是很熟,麻烦帮忙写一段代码参考参考!谢谢!
      

  2.   

    可以多步完成,先在主表A中插入一笔新记录,其ID为新的ID,其他字段值与要修改的ID对应的记录相同,然后UPDATE表B,将其ID更改为新的ID,然后删除表A中要修改ID的那条记录。
      

  3.   

    我的意思是你不能直接update已经被子表使用的ID,必须经过多步完成,所以是不能指望触发器来完成这项工作的。
      

  4.   

    我的程序不用触发器很不好办。在网页中自动生成的sql,很不好改,所以只有在数据库上打主意。那用别的,存储过程,能行吗?
      

  5.   

    那你在before update 触发器中判断若:new.id与:old.id不同(或者你的触发器就是update of id),此时通过动态SQL,'alter table temp disable constraint temp_fk'将这个外键约束先disable,然后更新子表,在after update 触发器中再通过'alter table temp enable constraint temp_fk' 使这个外键约束enable.
      

  6.   

    关键是 'alter table temp disable constraint temp_fk' 这个动态sql能不能执行?因为在trigger里面,这个表示被锁定的。我对这个不熟,见笑!
      

  7.   

    我用 select * from user_constraints where TABLE_NAME='ARCHFLIST' 
    --'ARCHFLIST'  就是我的子表,得出来的  FK_ARCHFLIS_REF_11545_ARCHF 就是这个外键约束,对吧!'alter table temp disable constraint FK_ARCHFLIS_REF_11545_ARCHF',是这样吗?多谢空杯大哥关照!
      

  8.   

    是这样的,你的触发器是建立在主表上的,而disable和enable的操作是针对子表的,不过我也不知这样的动态SQL语句是否能在trigger里执行?
    若还是不行,你就在程序里,在update主表的ID前后直接执行这两句SQL语句吧!
      

  9.   

    我在主标上建了了一个trigger如下:CREATE OR REPLACE TRIGGER ARCHF_TRIGGER1 
    BEFORE  UPDATE  
    ON XBDKMIS.ARCHF 
    FOR EACH ROW  
      
    DECLARE  
    oldID  archf.docid%type;  
    newID  archf.docid%type; 
    BEGIN 
    newID:=:new.docid; 
    oldID:=:old.docid; 
    if newID!=oldID then 
    execute immediate 'alter table archflist disable constraint FK_ARCHFLIS_REF_11545_ARCHF'; 
    execute immediate 'update table archflist set docid=newID where docid=odlID'; 
    execute immediate 'alter table archflist enable constraint FK_ARCHFLIS_REF_11545_ARCHF'; 

    end if; 
    END; 
    执行修改操作的时候,出现如下错误:can't commit in trigger;
    error during excute trigger;
    ...
    好像没有什么好的解决办法。上面的办法也不行。可是这个表已经建立好了,这种效果看来在触发其中是不能达到的了。不止各位还有何高见?
      

  10.   

    我去年回答过一模一样的问题,解决方案如下:-- 建父表
    SQL> create table a(id integer primary key);
    Table created.-- 建子表
    SQL> create table b(id integer);
    Table created.--建立一个deferrable(可延时检验的外键,并设置初始校验方式为延时)
    --这一部大概是最关键的,所谓延时校验就是在commit的时候才对约束进行合法性检查
    --而建立约束的时候如果不指定延时校验那就是及时校验,dml完成以后立即进行合法性检查
    SQL> alter table b add constraint fk_b_a foreign key (id) references a(id) deferrable initially deferred;
    Table altered.--插入测试数据
    SQL> insert into a values (1);
    1 row created.
    SQL> insert into a values (2);
    1 row created.
    SQL> insert into b values (1);
    1 row created.
    SQL> insert into b values (2);
    1 row created.--建立一个触发器保证父子表中的纪录同步
    SQL> create or replace trigger tri_a_1 before update on a for each row
      2  begin
      3    update b set id=:new.id
      4     where b.id=:old.id;
      5  end;
      6  /Trigger created.--更新父表数据
    SQL> update a set id=3 where id=1;
    1 row updated.--检查结果
    SQL> select * from a;
            ID
    ----------
             3
             2--结果是看到子表中的纪录自动被更新了
    SQL> select * from b;
            ID
    ----------
             3
             2
      

  11.   

    不知道我有没有误解你的意思,下面是实验
    CREATE OR REPLACE TRIGGER trg_update_father
    AFTER UPDATE ON father FOR EACH ROW
    BEGIN
         UPDATE child SET id=:new.id WHERE
         id=:old.id;
    END trg_update_father;^_^>select * from father
      2  ;        ID
    ----------
             1
             2
             3^_^>select * from child;        ID
    ----------
    SERIAL
    ----------------------------------------------------------------------------------------------------
             1
    hello         2
    world         3
    goodbye
    ^_^>update father set id=4 where id=1;已更新 1 行。^_^>select * from father;        ID
    ----------
             4
             2
             3^_^>select * from child;        ID
    ----------
    SERIAL
    ----------------------------------------------------------------------------------------------------
             4
    hello         2
    world         3
    goodbye