【问题标题】:How can I drop a "not null" constraint in Oracle when I don't know the name of the constraint?当我不知道约束的名称时,如何在 Oracle 中删除“非空”约束?
【发布时间】:2011-02-02 04:39:04
【问题描述】:

我有一个对字段有 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 专业知识),任何可能具有系统生成名称的约束都可能与它相关联的方式可能并不普遍正确,这种方法可以在没有必须知道它的名字。在逻辑上删除该约束时,是否总有一种方法可以避免必须知道系统命名约束的名称?

【问题讨论】:

  • 只是为了满足您的好奇心:NOT NULL 约束是 Oracle 中的 only 约束类型,您可以删除它而无需知道约束的名称。您需要知道约束名称的所有其他约束类型。

标签: oracle plsql constraints


【解决方案1】:
alter table MYTABLE modify (MYCOLUMN null);

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

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

【讨论】:

  • 这看起来好得令人难以置信,但它绝对可以处理我目前的情况,而且非常简单! oracle中是否存在约束名称可以由系统生成但无法写入sql以避免这样的约束名称的情况?
  • 谢谢...事实证明 not null 约束是我的架构中唯一可能以这种方式影响我的系统命名约束。
【解决方案2】:

试试:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      -- 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;
      

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

      答案来自 Michael McLaughlin 的博客:http://michaelmclaughlin.info/db1/lesson-5-querying-data/lab-5-querying-data/ 来自他的数据库设计 I 课程。

      【讨论】:

        【解决方案5】:

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

        选择约束名称 来自 all_cons_columns 其中表名 = [表名] 和 column_name = [COLUMN_NAME];

        【讨论】:

          【解决方案6】:

          当我将结构复制到临时表时发生了类似的事情,所以我删除了 not 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;
          

          【讨论】:

          【解决方案7】:

          如果在创建表时对列 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;

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-11-08
            • 2012-02-18
            • 2011-04-26
            • 2016-07-12
            • 2021-08-18
            • 2012-09-05
            • 2023-03-10
            • 2014-09-12
            相关资源
            最近更新 更多