【问题标题】:drop index or constraint without knowing its name for Oracle在不知道 Oracle 名称的情况下删除索引或约束
【发布时间】:2012-02-18 23:24:37
【问题描述】:

在 oracle 数据库中,我有一个外键,但不知道它的名称,只有 column_name 和 reference_column_name。 我想编写一个 sql 脚本,如果存在这个外键,它应该删除它,所以这是我使用的代码:

declare
 fName varchar2(255 char);
begin
 SELECT x.constraint_name into fName FROM all_constraints x
 JOIN all_cons_columns c ON
 c.table_name = x.table_name AND c.constraint_name = x.constraint_name
 WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME';
end;

这个脚本的输出是“匿名块完成”,所以它是成功的,但是当我添加drop部分时:

declare
 fName varchar2(255 char);
begin
 SELECT x.constraint_name into fName FROM all_constraints x
 JOIN all_cons_columns c ON
 c.table_name = x.table_name AND c.constraint_name = x.constraint_name
 WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME';
 if (fName != '') THEN
  alter table MY_TABLE_NAME drop constraint fName;
 end if;
end;

然后我得到这个:

错误报告:ORA-06550:第 9 行,第 5 列:PLS-00103:遇到 预期以下之一时的符号“ALTER”:

begin case 为 goto 声明退出 if loop mod null pragma raise 在

那么谁能告诉我这里有什么问题?

我也尝试将所有内容都放入一个函数中:

declare
  function getFName return varchar2 is
    fName varchar2(255 char);
  begin
   SELECT x.constraint_name into fName FROM all_constraints x
   JOIN all_cons_columns c ON
   c.table_name = x.table_name AND c.constraint_name = x.constraint_name
   WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME';

   return fName;
  end;
begin
  if getFName() != '' then
   alter table all_events drop constraint getFName(); 
  end if;
end; 

结果与语句“alter table”引起的错误相同

这个也没有帮助:

alter table all_events drop constraint
   (SELECT x.constraint_name into fName FROM all_constraints x
   JOIN all_cons_columns c ON
   c.table_name = x.table_name AND c.constraint_name = x.constraint_name
   WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME');

输出是:

错误报告:SQL 错误:ORA-02250:缺少或无效的约束名称 02250. 00000 - “缺少或无效的约束名称” *原因:约束名称丢失或无效。 *操作:为约束名称指定一个有效的标识符名称。

对于 sql server (MS SQL) 来说,这很容易做到。只需用 @ 声明一个变量并设置它,然后使用它。在 oracle 上,我不知道它有什么不工作...

【问题讨论】:

    标签: sql oracle constraints sql-drop


    【解决方案1】:

    这是删除所有为列键入“R”的约束的方法:

    begin
        FOR rec IN (SELECT x.constraint_name fName FROM all_constraints x
            JOIN all_cons_columns c ON
            c.table_name = x.table_name AND c.constraint_name = x.constraint_name
            WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME')
        LOOP
            EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE_NAME DROP CONSTRAINT "' || rec.fName || '"';
        END LOOP;
    end;
    

    【讨论】:

      【解决方案2】:

      您的原始版本大部分都很好,只是您不能在 PL/SQL 块中直接执行 DDL;相反,您必须将其包装在 EXECUTE IMMEDIATE:

      execute immediate 'alter table MY_TABLE_NAME drop constraint "' || fName || '"';
      

      即使在编译时已知约束名称也是如此,但在您的情况下它是双重正确的,因为fName 不是约束名称,而是包含约束名称的变量.

      还有,这个:

      if (fName != '') THEN
      

      无效/没有意义,因为在 Oracle 中 '' 表示 NULL。你应该写

      IF fName IS NOT NULL THEN
      

      改为。

      【讨论】:

      • 嘿只是一个关于这个的附加问题:理论上,如果表 A1 的列 C1 引用表 A2 的 C2 和 C1 引用表 A3 的 C3,我将获得多个约束名称,所以我会得到 C1->C2 和 C1->C3 的名称,所以问题是我在哪里可以加入我引用的列的信息???
      • @radio:在all_constraints 上,(r_owner, r_constraint_name) 实际上是一个外键;您可以加入all_constraints 以获取有关所引用列的信息。 (在 Oracle 内部,外键被实现为另一个约束的外键。当您考虑 DBMS 需要做什么来强制执行外键约束时,这是有道理的。)
      • @radio:顺便说一句,你的“理论”问题让我有点担心,因为你的代码还有其他更大的问题——例如,你使用 all_constraints 和 @987654332 @ 而不检查 owner,并且您不检查以确保 'MY_COLUMN_NAME' 是外键中的唯一列。所以你的代码不是通用的。我假设您计划在具有很多其他信息的特定情况下使用它,但由于某种原因只是缺少约束名称。如果您需要通用代码,则需要修复很多问题。
      • 嗯,你说得对,这不是通用的。我实际上确切地知道我的源表应该是什么样子,我不希望任何其他所有者具有相同的表名称/列,所以我不必担心其他所有者等,对吧?我只需要进行一些手动修改以将我的源表带到特定的目标状态,仅此而已。
      • 如何检查 'MY_COLUMN_NAME' 是否是外键或索引中的唯一列(现在我也需要这个),是否有额外的 sys 表连接?我已经添加了所有者
      猜你喜欢
      • 1970-01-01
      • 2023-03-10
      • 2011-04-26
      • 2021-01-05
      • 2013-08-06
      • 2010-11-28
      • 2010-11-23
      • 1970-01-01
      • 2015-03-22
      相关资源
      最近更新 更多