Oracle - 将列设置为NULL不会删除CHECK约束

时间:2014-06-11 12:07:22

标签: sql oracle alter-table

我的表中有NOT NULL列,我需要允许null值。我知道解决方案

alter table USER modify(FIRST_NAME null);

但似乎在我的情况下不起作用,因为它不会删除现有的 CHECK ("FIRST_NAME" IS NOT NULL)。此约束具有系统名称SYSxxxxx,因此我也无法直接禁用此约束(因为名称在环境上有所不同)。我假设它与事实有关,这个表是通过将DUMP加载到数据库中创建的(由于某种原因,Oracle失去了列属性和CHECK之间的连接)。知道这是怎么发生的,以及如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

创建NOT NULL约束并检查:

create table tmp(
n1 number not null,
n2 number check (n2 is not null)
)
/
select * from all_constraints where table_name = 'TMP'
/

输出(减法):

constraint_name   constraint_type   table_name   search_condition
---------------   ---------------   ----------   ----------------
SYS_C0036560      C                 TMP          "N1" IS NOT NULL
SYS_C0036561      C                 TMP          n2 is not null

所以,它们在字典中看起来几乎相同。

我认为,你需要一个脚本,通过表/列组合找到约束名,然后(使用动态sql)删除/禁用它。


更多想法:)有区别!你能检查下面查询的输出表吗?

select column_name, NULLABLE from USER_TAB_COLS where table_name = 'TMP'

COLUMN_NAME                    NULLABLE
------------------------------ --------
N1                             N        
N2                             Y    

我做完

alter table tmp drop constraint SYS_C0036560

N1列可以为空:

COLUMN_NAME                    NULLABLE
------------------------------ --------
N1                             Y        
N2                             Y    

如果这对你有用,那么生成一个脚本

select 'alter table ' || table_name || ' drop constraint ' || constraint_name || ';'
from all_constraints where table_name in ( 'TMP', 'list of your tables' )
and constraint_type = 'C' 
and instr(upper(search_condition, 'IS NOT NULL') > 0
and replace(
substr(upper(search_condition), 1, instr(search_condition, ' ')), 
'"', '')  in ('FIRST_NAME', 'maybe some other columns names')

答案 1 :(得分:1)

好吧,我带来了这个解决方案

alter table USER rename column FIRST_NAME to FIRST_NAME_OLD;
alter table USER ADD FIRST_NAME VARCHAR2(40 CHAR) NULL;
update USER set first_name=first_name_old;
alter table USER drop column FIRST_NAME_OLD;

我知道大型表可能存在性能问题,但这不是我的情况