新增非空约束字段在不同版本中的演进

简介: 开发提了一个数据库变更需求,新增一字段,没有NOT NULL非空约束,但有默认值为NULL。看起来有些奇怪,因为若字段允许NULL,其默认值就是NULL,不用显示声明,可以创建一个无DEFAULT NULL的新增字段再查看desc表结构,就可以证明这点。

开发提了一个数据库变更需求,新增一字段,没有NOT NULL非空约束,但有默认值为NULL。看起来有些奇怪,因为若字段允许NULL,其默认值就是NULL,不用显示声明,可以创建一个无DEFAULT NULL的新增字段再查看desc表结构,就可以证明这点。

基于这问题,引申出的NOT NULL字段问题还有不少,也是比较容易忽视的一些细节,例如杨长老最近连续发表过两篇关于NOT NULL字段的文章确实很有启发,

非空字段空值对查询的影响
http://yangtingkun.net/?p=1481
非空字段空值的产生
http://yangtingkun.net/?p=1483

具体各位可以参考这两篇博文,简单总结一下,11.2.0.3的库,
1.使用where type is null和is not null得到的记录结果判断值为非空。
2.使用dump(type)和nvl(type, ‘is null’)得到的记录结果判断值为空。
表定义中此字段为DEFAULT ” NOT NULL,事实证明(2)是正确的,之所以有(1)的结论,原因是CBO太智能了。
对于IS NOT NULL,type字段定义为NOT NULL,此SQL明显违反了表中的约束条件,则会在执行计划最上层增加一个NULL IS NOT NULL恒为假的条件,根本不需要真正执行这个SQL,直接返回0条记录。
对于IS NULL,由于查询条件满足约束的条件,因此Oracle会做全表扫描,并且省略了type is not null的过滤,直接返回所有记录,就造成了type非空的假象。
出现以上问题的核心,还是为何有为空的记录存储于有NOT NULL非空约束的表中。原因就是11g新特性,新增一个有默认值的NOT NULL约束的字段,默认值不会像以前一样,插入每条记录中,而是会存储于一张数据字典表sys.ecol$,Oracle允许NOT NULL列默认值为NULL,因此对于11g来说,需要禁止DEFAULT为NULL的这种行为。

这种新增非空约束字段在不同版本中确实有一些细节的变化,下面做一些简单测试。
首先,创建测试表,插入一条数据,新增列为NOT NULL且默认值是”的字段:

create table bisal (id number);
insert into bisal values(1);
alter table bisal add name varchar2(10) default '' not null;

10.2.0.3库,从报错信息看ORA-01407,不能更新NAME列为空,可以看出此时是要将表中已存在记录的新列name做UPDATE设置为默认值的操作,由于有非空约束,因此不允许。
这里写图片描述

11.2.0.1库,可以新增字段,表中已存记录该值确实为空,即允许一个有NOT NULL约束的字段包含NULL值。
这里写图片描述
关于这新特性的好处,可以参考之前写的
《alter table新增字段操作究竟有何影响?(上下篇)》
http://blog.csdn.net/bisal/article/details/45418303
http://blog.csdn.net/bisal/article/details/49182025

12.1.0.2库,我们可以看出和10g一样,禁止新增一个默认值为NULL的NOT NULL约束字段,但报错信息变了,ORA-01758: table must be empty to add mandatory (NOT NULL) column,这个错误号在之前的版本有定义,不是新号。
这里写图片描述
根据错误提示,我们删除表中数据,再新增字段,可以增加,但不能再插入一条NULL至这个非空约束字段。
这里写图片描述

我们再看下官方文档的描述,11g中对于新增默认值字段的描述部分,明确指出NOT NULL约束包含默认值的情况下,是将默认值存储于数据字典中。
这里写图片描述

12c中描述允许为空的字段,若有默认值,不会更新已存数据,而是会借助数据字典完成存储,这种新特性的适用范围更广了。
这里写图片描述
由于我没有12c的sys真实环境,朋友可以自己尝试下,有机会我会自己再验证下。

至此,12c修复了11g中这个非空约束字段允许保存空值的bug,同时又支持11g新增默认值非空字段使用数据字典存储的特性,并且做了扩展支持,满足范围更大了。

小问题隐藏了大智慧。

目录
相关文章
|
22天前
|
分布式计算 架构师 大数据
Dataphin常见问题之添加关联维表后,在业务限定找不到关联表字段如何解决
Dataphin是阿里云提供的一站式数据处理服务,旨在帮助企业构建一体化的智能数据处理平台。Dataphin整合了数据建模、数据处理、数据开发、数据服务等多个功能,支持企业更高效地进行数据治理和分析。
|
9月前
|
存储
PG11新特性解读:新增非空默认值字段不需要重写表
PG11新特性解读:新增非空默认值字段不需要重写表
99 1
|
7月前
|
存储 XML SQL
浅谈扩展字段设计
浅谈扩展字段设计
206 0
|
10月前
|
SQL Java 关系型数据库
数据库表主键类型设计踩坑记录
数据库表主键类型设计踩坑记录
60 0
|
存储 关系型数据库 索引
错误代码:1822无法添加外键约束缺少约束索引
错误代码:1822无法添加外键约束缺少约束索引
361 0
|
Oracle 关系型数据库 索引
唯一约束和唯一索引区别
唯一约束和唯一索引区别
754 0
|
SQL 数据库 索引
开发指南—透明分布式—变更表类型及拆分规则
PolarDB-X新增支持变更表的类型(即在单表、拆分表和广播表三者间进行相互转换),和变更拆分表的拆分规则(包括拆分函数或拆分列)。本文介绍相关语法和示例。
开发指南—透明分布式—变更表类型及拆分规则
|
关系型数据库 数据库 PostgreSQL
开发踩坑记录之三:PostgreSQL数据库表唯一性约束失效
在设计数据库表过程中,我们通常会对数据库表进行唯一性约束,以防止事务不一致导致的相同数据的重复插入问题。但是在实际开发中发现,即使设置了数据库表的唯一性约束,仍然出现了相同数据重复插入的问题。
|
存储 SQL JSON
如何不改表结构动态扩展字段?
痛点 软件行业唯一不变的就是变化,比如功能上线之后,客户或 PM 需要对已有的功能增加一些合理的需求,完成这些工作必须通过添加字段解决,或者某些功能的实现需要通过增加字段来降低实现的复杂性等等。
640 0
如何不改表结构动态扩展字段?
|
SQL 数据库
数据库必知词汇:非空约束(NOT NULL)
NOT NULL 约束强制列不接受 NULL 值。NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。
687 0