SQL列定义:默认值和非空冗余?

SQL列定义:默认值和非空冗余?,sql,default-value,ddl,notnull,Sql,Default Value,Ddl,Notnull,我已经多次看到以下语法定义了create/alter DDL语句中的列: ALTER TABLE tbl ADD COLUMN col VARCHAR(20) NOT NULL DEFAULT "MyDefault" 问题是:既然指定了默认值,是否还需要指定列不应接受null?换言之,默认值不表示非空冗余吗?即使使用默认值,也可以始终使用NULL覆盖列数据 notnull限制不允许您在使用NULL值创建该行后更新该行。默认值是在insert/update语句中没有显式值时插入的值。假设您的DD

我已经多次看到以下语法定义了create/alter DDL语句中的列:

ALTER TABLE tbl ADD COLUMN col VARCHAR(20) NOT NULL DEFAULT "MyDefault"

问题是:既然指定了默认值,是否还需要指定列不应接受null?换言之,默认值不表示非空冗余吗?

即使使用默认值,也可以始终使用
NULL
覆盖列数据


notnull
限制不允许您在使用
NULL
值创建该行后更新该行。默认值是在insert/update语句中没有显式值时插入的值。假设您的DDL没有
notnull
约束:

ALTER TABLE tbl ADD COLUMN col VARCHAR(20) DEFAULT 'MyDefault'
然后你可以发布这些声明

-- 1. This will insert 'MyDefault' into tbl.col
INSERT INTO tbl (A, B) VALUES (NULL, NULL);

-- 2. This will insert 'MyDefault' into tbl.col
INSERT INTO tbl (A, B, col) VALUES (NULL, NULL, DEFAULT);

-- 3. This will insert 'MyDefault' into tbl.col
INSERT INTO tbl (A, B, col) DEFAULT VALUES;

-- 4. This will insert NULL into tbl.col
INSERT INTO tbl (A, B, col) VALUES (NULL, NULL, NULL);
或者,您也可以根据以下标准在
UPDATE
语句中使用
DEFAULT

-- 5. This will update 'MyDefault' into tbl.col
UPDATE tbl SET col = DEFAULT;

-- 6. This will update NULL into tbl.col
UPDATE tbl SET col = NULL;
注意,并非所有数据库都支持所有这些SQL标准语法。添加
notnull
约束将导致语句
4,6
出错,而
1-3,5
仍然是有效语句。所以要回答你的问题:不,它们不是多余的。

我认为不是

如果列不接受空值,那么没有什么可以阻止您将空值插入字段。据我所知,默认值仅适用于创建新行

如果设置了NOTNULL,则不能在字段中插入null值,因为它会引发错误


可以将其视为防止空值的故障保护机制。

我的SQL老师说,如果同时指定
DEFAULT
值和
notnull
NULL
DEFAULT
应始终在
notnull
NULL
之前表示

像这样:

ALTER TABLE tbl ADD列col VARCHAR(20)默认值“MyDefault”不为空

ALTER TABLE tbl ADD列col VARCHAR(20)默认值“MyDefault”NULL

换句话说,默认渲染不是空冗余的吗

不,这不是多余的。扩展的被接受的答案。对于可为NULL的列
col
,awe可以插入NULL,即使定义了默认值:

CREATE TABLE t(id INT PRIMARY KEY, col INT DEFAULT 10);

-- we just inserted NULL into column with DEFAULT
INSERT INTO t(id, col) VALUES(1, NULL);

+-----+------+
| ID  | COL  |
+-----+------+
|   1 | null |
+-----+------+
Oracle为此类场景引入了额外的语法,以使用默认值覆盖显式NULL
default ON NULL

CREATE TABLE t2(id INT PRIMARY KEY, col INT DEFAULT ON NULL 10);
-- same as
--CREATE TABLE t2(id INT PRIMARY KEY, col INT DEFAULT ON NULL 10 NOT NULL); 

INSERT INTO t2(id, col) VALUES(1, NULL);

+-----+-----+
| ID  | COL |
+-----+-----+
|  1  |  10 |
+-----+-----+
在这里,我们尝试插入NULL,但得到默认值

如果指定ON NULL子句,则当后续INSERT语句尝试分配计算结果为NULL的值时,Oracle数据库将分配默认列值

指定ON NULL时,将隐式指定NOT NULL约束和NOT DERRABLE约束状态


对于自12c以来的Oracle,默认值为NULL,这意味着
非NULL
约束

ALTER TABLE tbl ADD (col VARCHAR(20) DEFAULT ON NULL 'MyDefault');

论空

如果指定ON NULL子句,则Oracle数据库将分配 后续INSERT语句尝试执行时的默认列值 指定一个计算结果为NULL的值

当您指定ON NULL时,NOT NULL约束和NOT DEERRABLE 约束状态是隐式指定的。如果指定内联 与NOT NULL和NOT DERRABLE冲突的约束,然后 出现错误


嘿,谢谢你的参与。不过,这并不能解决当前的问题,而且这两种排序都是完全有效的。我发现在手动编写表脚本时更容易将默认值放在末尾,因为空值和非空值会更好地对齐。好吧,我想你也是对的。我不明白为什么我的课程明确地说了我在答案上写的东西。我知道我的回答并没有真正解决这个问题,但我发现一条评论不太可读。在(主观的)最佳实践和规则之间有区别。保持一致的样式不是一个坏主意,但在这种特殊情况下,我个人更喜欢在默认值之前不为NULL。不管怎样,你也可以写评论而不是答案,这会更合适。这可能无法回答问题。但这正是我想要的。谢谢。我认为这应该重新表述:“NOT NULL限制不允许您在使用NULL值创建该行后更新该行”。当然,可以更新包含NOT NULL列的行,但不能将NULL作为该列的值进行更新。此外:我假设创建一行意味着插入一行。INSERT语句对于使用NOT null指定的列不能有null值。您说的是“创建新规则”。你打算说“创建一个新的行”吗?我认为这是这个问题的一个更实际的答案。@bielawski将近8年后,我开始纠正这个错误:)这应该是被接受的答案。OP问了一个简单的问题,答案是“不”。不过,文档需要解释和示例。我访问了您的链接(到您的博客帖子),希望看到对查询性能的巨大影响的解释(可能有一些数字),但只看到它简单地重申了它的影响。无意冒犯,但这个链接有点误导。@SethFlowers:谢谢你的指点,Seth。这篇链接文章同时被编辑。我将查看是否可以链接其他内容,或者删除链接。现在看来,你是绝对正确的,这并没有给这里的答案增加任何价值。谢谢-我希望我没有听起来粗鲁。我刚看到链接,就想“是的,那绝对是我想读的东西”——然后有点失望:)@SethFlowers:不用担心。我完全同意。拯救我的是:在过去的几年里,我的博客技能大大提高了:)