2

我有一个根本不应该有任何 NULL 值的表。当我设置 NOT NULL 约束时,它不允许该语句并且它因约束错误而失败。仅当插入语句中未引用该列时,才会发生默认约束。

我们怎样才能解决这个问题?如果插入语句的任何列具有 NULL 值,则必须采用 DEFAULT 值而不是 NULL 值。

create table temp1 (col0 int, col1 int default 0);
insert into temp1 (col0) values (1); --> col0 -> 1 and col1 ->0
insert into temp1 (col0,col1) values (1,NULL); --> col0 -> 1 and col1 -> NULL (I would expect a 0 here instead of NULL)
alter table temp1 (add column col2 int not null default 0); --> col2 -> 0 for all the existing rows
insert into temp1 (col0) values (2);  --> col0 -> 2 and col1 ->0 and col2-> 0
select * from temp1;

COL0 |COL1   |COL2
1    |0      |0   
1    |(null) |0   
2    |0      |0   
4

1 回答 1

2

将 NULL 转换为插入的列的默认值不是标准 SQL 的一部分。

正如您所观察到的,您可以从插入语句中省略该列,但这与插入 NULL 值不同。相反,实际上,列的 DEFAULT 的默认值为 NULL(SQL92 13.8 General Rules 4b);这就是为什么如果没有明确定义默认值,插入默认值会给出 NULL。

您也可以包含该列并使用关键字 DEFAULT(SQL92 7.1 通用规则 2)。WX2 目前不支持这种语法,但Kognitio计划在即将发布的 8.2 版本中添加它。

insert into temp1 (col0, col1) values (1, DEFAULT);

该标准仅允许您使用 DEFAULT,如上所示,而不是在复合表达式或插入选择语句中。

-- NOT VALID IN STANDARD SQL!
insert into temp1 (col0, col1) values (1, case when ... then 1 else DEFAULT end);

-- NOT VALID IN STANDARD SQL!
insert into temp1 (col0, col1) select C1, DEFAULT from ...;

您可以使用 COALESCE() 函数解决此问题。

insert into temp1 (col0, col1) select E1, COALESCE(E2, 0) from ...;

其他数据库通常也不允许将 NULL 转换为默认值:请参阅SQL ServerMySQLPostgresFirebird的类似问题。Oracle 确实有一种非标准语法来创建具有DEFAULT ON NULL的表列,这可以满足您的要求。

(Kognitio 可能会在复合表达式中添加 DEFAULT 或在未来版本中添加 DEFAULT ON NULL 作为扩展。)

于 2017-02-03T11:33:00.593 回答