Sql 在不知道其Oracle名称的情况下删除索引或约束

Sql 在不知道其Oracle名称的情况下删除索引或约束,sql,oracle,constraints,sql-drop,Sql,Oracle,Constraints,Sql Drop,在oracle数据库上,我有一个外键,不知道它的名称,只有列名和引用列名。 我想编写一个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

在oracle数据库上,我有一个外键,不知道它的名称,只有列名和引用列名。 我想编写一个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”(当预期出现以下情况之一时):

如果循环mod null pragma raise,则开始案例为goto声明退出
返回select update,而使用时,您的原始版本基本上没有问题,只是您不能在PL/SQL块中直接执行DDL;相反,您必须将其包装在一个
立即执行

execute immediate 'alter table MY_TABLE_NAME drop constraint "' || fName || '"';
即使在编译时知道约束名称,这也是正确的,但在您的情况下,这是双重正确的,因为
fName
不是约束名称,而是包含约束名称的变量

此外,这:

if (fName != '') THEN
无效/无意义,因为在Oracle中,
表示
NULL
。你应该写

IF fName IS NOT NULL THEN

相反。

这是如何删除列中键入“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;

嘿,还有一个问题:使用这个select语句,如果表A1的列C1引用表A2的C2,C1引用表A3的C3,我会得到多个约束名称,所以我会得到C1->C2和C1->C3的名称,所以问题是我在哪里可以加入我所引用的信息列???@radio:On
all\u constraints
(r\u owner,r\u constraints\u name)
实际上是一个外键;您可以重新连接到
所有约束
,以获取有关引用列的信息。(在Oracle中,外键是作为另一个约束的外键实现的。当您考虑DBMS需要做什么来执行外键约束时,这是有意义的。)@无线电:顺便说一下,您的“理论”关心让我有点担心,因为您的代码中还有其他更大的问题,例如,您使用
所有约束
所有约束列
,而不检查
所有者
,也不检查以确保
'MY\u COLUMN\u NAME'
是外键中的唯一列。所以你的代码不是通用的。我假设您计划在一个特定的环境中使用它,在这个环境中,您有很多其他信息,但由于某种原因只是缺少约束名称。如果你需要通用代码,你有很多事情要解决。你是对的,这不是通用代码。实际上,我知道我的源表应该是什么样子,我不希望有任何其他所有者具有相同的表名/列,所以我不必担心其他所有者等,对吗?我只需要做一些手动修改,将我的源表带到特定的目标状态,仅此而已。如何检查“my_COLUMN_NAME”是否是外键或索引中的唯一列(现在我也需要它),其他sys table连接?。我已经添加了所有者
IF fName IS NOT NULL THEN
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;