使用Oracle PL / SQL禁用表中的所有相关约束

时间:2015-02-13 17:12:01

标签: sql oracle oracle11g

CREATE OR REPLACE PROCEDURE disable_all_constraints
  (p_owner      IN VARCHAR2,
   p_table_name IN VARCHAR2)
IS
CURSOR check_status IS
      (SELECT status
       FROM all_constraints
       WHERE owner = p_owner 
       AND   table_name = p_table_name );
v_status     VARCHAR2(10);
BEGIN
  OPEN check_status;
  FETCH check_status
  INTO v_status;
  IF (check_status %NOTFOUND) 
  THEN
  DBMS_OUTPUT.PUT_LINE('No Constraints added to the table, give me another table to process!');
  ELSE
  FOR cur IN (SELECT owner, constraint_name , table_name 
              FROM   all_constraints
              WHERE  owner = p_owner
              AND    table_name = p_table_name) 
      LOOP
      EXECUTE IMMEDIATE 'ALTER TABLE '||cur.owner||'.'||cur.table_name||' MODIFY CONSTRAINT '||cur.constraint_name||' DISABLE CASCADE ';
      END LOOP;
  END IF;
  CLOSE check_status;
  SELECT DISTINCT status
  INTO   v_status 
  FROM   all_constraints
  WHERE  owner = p_owner
  AND table_name = p_table_name;
  IF  v_status = 'DISABLED'      
  THEN 
  DBMS_OUTPUT.PUT_LINE('All related constraints disable succesufully!');
  ELSE 
  DBMS_OUTPUT.PUT_LINE('Something went wrong, but that is impossible!');
  END IF; 
END;

所以我写了上面的文章。我测试了它,我认为它的工作做得很好。但我的问题是,它有多正确或多么糟糕?它可以以更容易和最佳的方式完成吗?感谢。

1 个答案:

答案 0 :(得分:3)

你这样做的方式没有任何本质上的错误,但是存在许多潜在问题和一些不必要的代码。

  • 你的第一个光标是不必要的,无论如何你要循环遍历ALL_CONSTRAINTS - 如果你没有进入循环那么表没有约束
  • 您可以尝试禁用已禁用的约束 - 您只需选择当前启用的那些约束。
  • 如果有多个状态,那么总是总是的最终选择将会始终失败,因为您将获得TOO_MANY_ROWS异常(用于返回多行)。这意味着永远不会输入您的最终ELSE语句。
  • 高度不可能在没有引发异常的情况下禁用约束。我甚至不打算进行最后的检查。

更一般地说,向屏幕输出信息很少有意义。它需要有人阅读它。如果一切正常,或者在发生错误时引发异常,那么通常会更好。

我会大量简化为类似下面的内容,它只是循环遍历非禁用的约束并禁用它们。

create or replace procedure disable_all_constraints (
    p_owner in varchar2
  , p_table_name in varchar2
    ) is

begin

   for cur in ( select owner || '.' || table_name as object
                     , constraint_name
                  from all_constraints
                 where owner = p_owner
                   and table_name = p_table_name
                   and status <> 'DISABLED'
                       ) loop

      execute immediate 'alter table ' || cur.object || ' 
                           modify constraint ' || cur.constraint_name || '
                           disable cascade';

   end loop;

end;

如果您觉得必须进行额外的检查和打印,可以更干净地完成:

create or replace procedure disable_all_constraints (
    p_owner in varchar2
  , p_table_name in varchar2
    )  is

   l_has_constraint boolean := False;
   l_ct number;

begin

   for cur in ( select owner || '.' || table_name as object
                     , constraint_name
                  from all_constraints
                 where owner = p_owner
                   and table_name = p_table_name
                   and status <> 'DISABLED'
                       ) loop

      l_has_constraint := True;
      execute immediate 'alter table ' || cur.object || ' 
                           modify constraint ' || cur.constraint_name || '
                           disable cascade';

   end loop;

   if not l_has_constraint then
       dbms_output.put_line('No Constraints added to the table.');
   else
       select count(*) into l_ct
         from all_constraints
        where owner = p_owner
          and table_name = p_table_name
          and status <> 'DISABLED'
              ;

       if l_ct = 0 then
          dbms_output.put_line('All related constraints disable successfully');
       else
          dbms_output.put_line('Something went wrong, but that is impossible');
       end if;
    end if;


end;