8

在 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”:

开始 case 声明退出 goto if loop mod null pragma raise return select update while with << close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe 06550. 00000 - “line %s, column %s:\n %s" *原因:通常是 PL/SQL 编译错误。*行动:

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

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

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) 来说,这样做很容易。只需用 @ 声明一个变量并设置它,然后使用它。在甲骨文上,我不知道它不起作用...

4

2 回答 2

7

您的原始版本大部分都很好,只是您不能在 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

反而。

于 2012-01-25T18:56:57.910 回答
3

这是删除列的所有类型为“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;
于 2013-02-03T09:54:40.163 回答