Sql 在不知道其Oracle名称的情况下删除索引或约束
在oracle数据库上,我有一个外键,不知道它的名称,只有列名和引用列名。 我想编写一个sql脚本,如果外键存在,它应该删除外键,因此我使用以下代码: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
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:Onall\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;