SQL 列定义:默认值而不是空冗余?
Posted
技术标签:
【中文标题】SQL 列定义:默认值而不是空冗余?【英文标题】:SQL Column definition : default value and not null redundant? 【发布时间】:2012-08-05 10:12:47 【问题描述】:我已经多次看到以下在创建/更改 DDL 语句中定义列的语法:
ALTER TABLE tbl ADD COLUMN col VARCHAR(20) NOT NULL DEFAULT "MyDefault"
问题是:既然指定了默认值,是否还需要指定该列不应接受 NULL ?换句话说,DEFAULT 不渲染 NOT NULL 是多余的吗?
【问题讨论】:
【参考方案1】:即使使用默认值,您也始终可以使用null
覆盖列数据。
NOT NULL
限制不允许您在使用 null
值创建该行后更新该行
【讨论】:
我认为这应该改写为:“NOT NULL 限制不会让您在使用 null 值创建该行后更新该行”当然可以更新具有 NOT NULL 列的行,它们只是可以' 不更新为 null 作为该列的值。此外:我假设创建一行意味着插入一行。对于用 NOT NULL 指定的列,INSERT 语句也不能有空值。【参考方案2】:DEFAULT
是在插入/更新语句中没有显式值的情况下将插入的值。假设,您的 DDL 没有 NOT NULL
约束:
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);
或者,您也可以根据SQL-1992 标准在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 标准语法。添加NOT NULL
约束将导致语句4, 6
出错,而1-3, 5
仍然是有效语句。所以回答你的问题:不,它们不是多余的。
【讨论】:
我访问了您的链接(指向您的博客文章),希望看到对查询性能的巨大影响的解释(可能带有一些数字),但只看到它简短地重申了它有影响。无意冒犯,但链接有点误导。 @SethFlowers:感谢您的指点,Seth。链接的文章在此期间进行了编辑。我会看看我是否可以链接其他东西,或者删除链接。就目前而言,您是绝对正确的,它不会为这里的答案增加任何价值。 谢谢 - 我希望我没有听起来粗鲁。我刚看到链接,就像“是的,这绝对是我想读的东西”——然后有点失望:)。 @SethFlowers:不用担心。我完全同意。拯救我:在过去的几年里,我的博客技巧大大提高了 :)【参考方案3】:我会说不是。
如果该列确实接受空值,那么没有什么可以阻止您在字段中插入空值。据我所知,默认值仅适用于创建新行。
如果设置了非空值,则不能在字段中插入空值,因为它会引发错误。
将其视为防止空值的故障安全机制。
【讨论】:
您说的是“创建新规则”。您是否打算说“创建新行”? 我认为这是这个问题的一个更实际的答案。 @bielawski 近 8 年后,我开始纠正这个错字:) 这应该是公认的答案。 OP 要求一个简单的问题,而答案只是“不”。但是,文档需要解释和示例。【参考方案4】:我的SQL老师说过,如果同时指定DEFAULT
值和NOT NULL
或NULL
,DEFAULT
应该总是在NOT NULL
或NULL
之前表达。
像这样:
ALTER TABLE tbl ADD COLUMN col VARCHAR(20) DEFAULT "MyDefault" NOT NULL
ALTER TABLE tbl ADD COLUMN col VARCHAR(20) DEFAULT "MyDefault" NULL
【讨论】:
您好,感谢您的参与。不过,这并没有解决手头的问题,而且这两种顺序都是完全有效的。当我手动编写表格脚本时,我发现将默认值放在最后更容易,因为这样 NULL 和 NOT NULL 值会更好地对齐。 好吧,我想你也是对的。我不明白为什么我的课程明确地说明了我在答案中所写的内容。我知道我的回答并没有真正解决问题,但我发现评论不是很可读。 (主观)最佳实践和规则之间存在差异。拥有一致的风格并不是一个坏主意,但在这种特殊情况下,我个人更喜欢在 DEFAULT 之前使用 NOT NULL。无论如何,您也可以写 cmets 而不是答案,这样会更合适。 这可能无法回答问题。但这正是我想要的。谢谢。【参考方案5】:换句话说,DEFAULT 不渲染 NOT NULL 冗余吗?
不,它不是多余的。扩展接受的答案。对于可以为空的列 col
,即使定义了 DEFAULT,我们也可以插入 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 为这种情况引入了额外的语法,以默认 DEFAULT ON NULL
覆盖显式 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 但取而代之的是默认值。
db<>fiddle demo
ON NULL
如果您指定 ON NULL 子句,则 Oracle 数据库会在后续 INSERT 语句尝试分配计算结果为 NULL 的值时分配 DEFAULT 列值。
当您指定 ON NULL 时,将隐式指定 NOT NULL 约束和 NOT DEFERRABLE 约束状态。
【讨论】:
【参考方案6】:对于自 12c 以来的 Oracle,您有 DEFAULT ON NULL
,这意味着 NOT NULL
约束。
ALTER TABLE tbl ADD (col VARCHAR(20) DEFAULT ON NULL 'MyDefault');
ALTER TABLE
为空
如果您指定 ON NULL 子句,则 Oracle 数据库分配 DEFAULT 列值,当随后的 INSERT 语句尝试 分配一个计算结果为 NULL 的值。
当您指定 ON NULL 时,NOT NULL 约束和 NOT DEFERRABLE 约束状态是隐式指定的。如果您指定内联 与 NOT NULL 和 NOT DEFERRABLE 冲突的约束,然后是 引发错误。
【讨论】:
以上是关于SQL 列定义:默认值而不是空冗余?的主要内容,如果未能解决你的问题,请参考以下文章