Oracle:动态设置表中的所有 NOT NULL 列以允许 NULL

Posted

技术标签:

【中文标题】Oracle:动态设置表中的所有 NOT NULL 列以允许 NULL【英文标题】:Oracle: Dynamically set all NOT NULL columns in a Table to allow NULL 【发布时间】:2015-02-06 20:47:33 【问题描述】:

我有一个包含 75 列以上的表格。 几乎所有的列都有 NOT NULL 约束。

如果执行一个巨大的 alter table modify 语句(其中包含每一列),我会收到一条错误消息,类似于“您不能将此字段设置为 NULL,因为它已经是 NULL”

我必须为多个表执行此操作,因此希望有一个动态解决方案。

能否动态查找所有不为 NULL 的列,并将它们设置为 NULL?

我见过几个类似的问题,但找不到 Oracle SQL 的解决方案。 Modify all columns in a table to 'not null' no matter what

【问题讨论】:

不确定为什么会收到该消息,除非您尝试将已经可以为 NULL 的列更改为 NULLable。我刚刚对 4 列表进行了测试,所有列都不是 NULL,然后在所有 4 列上运行 alter 到 NULL - 工作正常。您可以发布一个小的工作示例来重新创建您的问题吗?将其保留为 4 列 4 行表(这将足够大,我们可以看到问题)。包括创建表、插入、更改脚本。 【参考方案1】:

这是一个测试表,有两个非空列,一个空列:

create table zzz_mark_test_me (
     cust_id varchar2(20) not null, 
     cust_name varchar2(20) null,  
     cust_phone varchar2(20) not null
);

table ZZZ_MARK_TEST_ME created.

desc zzz_mark_test_me

Name       Null     Type         
---------- -------- ------------ 
CUST_ID    NOT NULL VARCHAR2(20) 
CUST_NAME           VARCHAR2(20) 
CUST_PHONE NOT NULL VARCHAR2(20) 

现在调用这个 SQL:

select 'alter table ' || table_name || 
    ' modify (' || column_name || ' null );' 
from user_tab_columns 
where table_name='ZZZ_MARK_TEST_ME' and nullable='N' 
order by column_id;

产生这个:

alter table ZZZ_MARK_TEST_ME modify (CUST_ID null );
alter table ZZZ_MARK_TEST_ME modify (CUST_PHONE null );

将输出复制/粘贴到 SQL*Plus 等中并调用:

alter table ZZZ_MARK_TEST_ME modify (CUST_ID null );
table ZZZ_MARK_TEST_ME altered.

alter table ZZZ_MARK_TEST_ME modify (CUST_PHONE null );
table ZZZ_MARK_TEST_ME altered.

现在,不再是 NOT NULL:

desc zzz_mark_test_me
Name       Null Type         
---------- ---- ------------ 
CUST_ID         VARCHAR2(20) 
CUST_NAME       VARCHAR2(20) 
CUST_PHONE      VARCHAR2(20) 

【讨论】:

我很欣赏这个答案附带的迷你教程!如果你愿意,你可以编辑它,以便执行立即语句进入那里。然后,从您和 Ponder 的答案中,这是两全其美的。无论如何,谢谢!【参考方案2】:

您可以使用此程序。在运行之前,您可以先注释掉包含“立即执行”的行以查看它执行的内容。 第一个参数是schema_name,第二个是table_name。

create or replace procedure proc_null(t_owner in varchar2, t_name in varchar2) as 
  v_exec_imm varchar2(1000);
begin
  for o in (select owner, column_name from all_tab_cols where owner=t_owner and table_name=t_name and nullable = 'N')
  loop
    v_exec_imm := 'alter table '||t_owner||'.'||t_name||' modify ('||o.column_name||' null) ';
    execute immediate v_exec_imm;  -- comment this line if You want, modifies table
    dbms_output.put_line( v_exec_imm );
  end loop;
end proc_null;

【讨论】:

当然这只不过是@Mark Stewart 写的,但我同时准备了这个解决方案,并且使用过程可以避免所有这些复制/粘贴。 是的,我很懒,永远记不起立即执行的 PL/SQL 语法;而且我也喜欢在执行之前查看生成的内容。 :)

以上是关于Oracle:动态设置表中的所有 NOT NULL 列以允许 NULL的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 12c - 根据不同表中的值动态生成 where 子句

oracle有没有方法把数据库表中的字段的所有数据中的某个字母或数字修改或替换

Oracle - 使用动态查询插入表

Oracle - 在所有表中搜索所有列中的数据

在所有表中的所有字段中搜索特定值 (Oracle)

在所有表中的所有字段中搜索特定值 (Oracle)