当我不知道约束名称时,如何在Oracle中删除“ not null”约束?


85

我有一个对字段具有NOT NULL约束的数据库,我想删除此约束。复杂的因素是,此约束具有系统定义的名称,并且该约束的名称在生产服务器,集成服务器和各种开发人员数据库之间不同。我们当前的过程是检入变更脚本,并且一个自动化的任务通过sqlplus针对目标数据库执行适当的查询,因此我希望可以直接发送到sqlplus的解决方案。

在我自己的数据库上,删除它的SQL将是:

alter table MYTABLE drop constraint SYS_C0044566

查询all_constraints视图时可以看到约束:

select * from all_constraints where table_name = 'MYTABLE'

但是我不确定如何使用SEARCH_CONDITIONLONG数据类型,或者即使知道了它的名称,也不确定如何最好地动态删除查找到的约束。

因此,如何创建一个更改脚本,可以根据其名称而不是其名称删除该约束?


编辑:@Allan的答案是一个很好的答案,但我担心(由于我缺乏Oracle专业知识),可能具有系统生成名称的任何约束都可能与它相关联,这并不是一种普遍的删除方法。约束而不必知道其名称。确实存在,在逻辑上删除该约束时,总会有一种避免必须知道系统命名约束名称的方法的方法吗?


3
只是为了满足您的好奇心:NOT NULL约束是Oracle中唯一可以删除而无需知道约束名称的约束类型。您需要知道所有其他约束类型。
杰弗里·肯普

Answers:


166
alter table MYTABLE modify (MYCOLUMN null);

在Oracle中,当为列指定不为null时,会自动创建not null约束。同样,将列更改为允许空值时,它们也会自动删除。

澄清修订后的问题:此解决方案仅适用于为“非空”列创建的约束。如果您在列定义中指定“主键”或检查约束而未命名,则最终将得到系统生成的约束名称(主索引为索引)。在这种情况下,您需要知道要删除的名称。最好的建议是通过确保为除“ not null”以外的所有约束指定一个名称来避免出现这种情况。如果您发现自己通常需要删除这些约束之一,则可能需要使用PL / SQL和数据定义表。


这看起来确实太好了,但是确实可以解决我目前的情况,而且很简单!在oracle中是否有任何情况可以使约束名称由系统生成,但无法编写sql来避免这样的约束名称?
克里斯·法默

1
谢谢...事实证明,not null约束是我的架构中唯一可能以这种方式影响我的系统命名约束。
克里斯·法默

16

尝试:

alter table <your table> modify <column name> null;

1

请记住,如果您想使可为空的字段是主键的一部分,则不能。主键不能包含空字段。


1

要发现使用的任何约束,请使用以下代码:

-- Set the long data type for display purposes to 500000.

SET LONG 500000

-- Define a session scope variable.

VARIABLE output CLOB

-- Query the table definition through the <code>DBMS_METADATA</code> package.

SELECT dbms_metadata.get_ddl('TABLE','[Table Described]') INTO :output FROM dual;

这实质上显示了如何创建引用表的create语句。通过了解如何创建表,您可以查看所有表约束。

答案来自Michael McLaughlin的博客:http : //michaelmclaughlin.info/db1/lesson-5-querying-data/lab-5-querying-data/来自他的Database Design I类。


0

我在尝试解决自定义检查约束时遇到了同样的问题,我需要对其进行更新以允许不同的值。问题在于,ALL_CONSTRAINTS没有办法确定将约束应用于哪一列。我设法做到这一点的方法是查询ALL_CONS_COLUMNS,然后按其名称删除每个约束并重新创建它。

从all_cons_columns中选择constraint_name,其中table_name = [TABLE_NAME]和column_name = [COLUMN_NAME];


0

当我将结构的副本复制到临时表时,发生了类似的事情,因此我删除了非null值。

DECLARE
   CURSOR cur_temp_not_null IS
        SELECT table_name, constraint_name  FROM all_constraints WHERE table_name LIKE 'TEMP_%' AND  owner='myUSUARIO';

   V_sql VARCHAR2(200); 

BEGIN
  FOR c_not_null IN cur_temp_not_null
   LOOP
     v_sql :='ALTER TABLE ' || c_not_null.table_name || ' DROP CONSTRAINT '|| c_not_null.constraint_name;
     EXECUTE IMMEDIATE  v_sql;     
  END LOOP;
END;

堆栈溢出是仅英语的站点。但是,有堆栈溢出enespañol。看到我的编辑。
help-info.de

0

如果在创建表的过程中在状态STATUS列上创建了约束而没有名称,则Oracle将为其分配一个随机名称。不幸的是,我们不能直接修改约束。

删除链接到状态STATUS的未命名约束的步骤

  1. 将STATUS字段复制到新字段STATUS2中
  2. 在STATUS2上定义CHECK约束
  3. 将数据从STATUS迁移到STATUS2
  4. 删除状态栏
  5. 将STATUS2重命名为STATUS

    ALTER TABLE MY_TABLE ADD STATUS2 NVARCHAR2(10) DEFAULT 'OPEN'; ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_CHECK_STATUS CHECK (STATUS2 IN ('OPEN', 'CLOSED')); UPDATE MY_TABLE SET STATUS2 = STATUS; ALTER TABLE MY_TABLE DROP COLUMN STATUS; ALTER TABLE MY_TABLE RENAME COLUMN STATUS2 TO STATUS;

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.