不再迷惑,无值和NULL值

在关系型数据库的世界中,无值和NULL值的区别是什么?一直被这个问题困扰着,甚至在写TSQL脚本时,战战兢兢,如履薄冰,害怕因为自己的一知半解,挖了坑,贻害后来人,于是,本着上下求索,不达通幽不罢休的决心(开个玩笑),遂有此文。

学习过关系型数据库的伙伴都知道,NULL是指不确定的值,在数据库中绝对是噩梦的存在;而空值,一般对字符串类型而言,指没有任何值的字符串类型,为字符类型的变量设置为空值:set @vs=‘‘,空值跟无值不同。有人可能会问,无值是什么?无值,是指数据表中没有任何数据。无值和不确定值,单从字面意思上来看,两者之间的定义很清楚,一旦深究,这两者之间的关系,有时令人十分迷惑(confused),这是因为,在特定条件下,无值会转换为NULL值。

一,举个栗子,理解无值和NULL值的区别

比如,创建一个临时表,在不插入任何数据时,该数据表是空的,没有任何值,对其执行select命令,将不会返回任何数据值:

create table #temp
(
id int null
)

创建一个标量类型的变量,在不初始化时,该变量的值是不确定的,其值是NULL:

declare @vs int

创建一个表类型变量,在不初始化时,该表变量没有任何数据,是无值的:

declare @vt as table
(
id int null
)

总结一下,声明一个标量型变量,如果没有对变量进行初始化,其值是不确定的,是NULL值;对于表变量,临时表和基础表,如果没有插入任何数据,该表没有任何数据,是无值的。

二,无值和NULL值的转换

在开始本节之前,先为变量赋值,简单的一个select命令就可以完成变量的赋值:

select @vs=1

有些朋友思维比较活跃,立马会想到:“用select命令可以从表中取值为变量赋值”,对,但是,赋值方法不是我求索的重点,我关注的是从表中取值为变量赋值的结果。

1,从空表中为变量赋值

如果数据表是空表,没有任何值,那么数据库引擎不会执行赋值语句,变量保持原有值不变:

select @vs=id
from #temp

但是,如果采用以下方式,那么数据库引擎会执行赋值语句,由于空表不返回任何值,数据库引擎会把无值转换为不确定值NULL:

select @vs=(select top 1 id
from #temp)

诧异吗?无值和NULL值的转换,居然从不起眼的变量赋值开始。注意,当不返回任何值时,数据库引擎不确定返回值,就把无值转换为NULL值。

2,从空表中计算聚合

空表是没有任何数据的表,计算聚合会产生怎样的结果?

select count(0) as count_all
    ,count(id) as count_id
    ,max(id) as max_id
    ,min(id) as min_id
    ,avg(id) as avg_id
    ,sum(id) as sum_id
from #temp

当统计数据行数时,返回的是0;当计算聚合函数(max,min,avg和sum)的聚合值时,由于无值可以聚合,数据库引擎不能确定这些聚合函数的返回值,因此,数据库引擎返回NULL值。

三,聚合函数忽略NULL值

一般情况下,除了count(0),count(*)之外,聚合函数都会忽略NULL值,而统计非NULL值,如果读者有疑问,可以查看我的博客《TSQL 聚合函数忽略NULL值》。如果只知聚合函数忽略NULL值,而不知空表也会产生结果为NULL的聚合值,轻易得出聚合函数不会返回NULL值的定论,那就很尴尬。楼主曾遇到过一次“意外”,在一次调试脚本代码的过程中,我遇到max聚合函数返回NULL值的情况,当时一脸懵逼,直接怀疑自己之前的所学。

当聚合列值都是NULL值时,由于聚合函数忽略NULL值,因此,当计算聚合函数(max,min,avg和sum)的聚合值时,由于无值可以聚合,数据库引擎不能确定这些聚合函数的返回值,因此,数据库引擎返回NULL值。

insert into #temp(id)
values(null)

select count(0) as count_all
    ,count(id) as count_id
    ,max(id) as max_id
    ,min(id) as min_id
    ,avg(id) as avg_id
    ,sum(id) as sum_id
from #temp

聚合函数(max,min,sum,avg和count)忽略null值,但不代表聚合函数不返回null值:如果数据表为空表,或聚合列值都是null,那么max,min,sum,avg聚合函数返回null值,而count 聚合函数返回0。聚合函数的共性:Null values are ignored。

不再迷惑:当不返回任何值时,数据库引擎不确定返回值,就把无值转换为NULL值。

附:select和set通过查询(query)对变量赋值的差异:

差异1:set 只能对变量赋值一次,而select 可以对变量赋值多次,变量值是最后一次赋值的结果

set @variable=(select top 1 column_name from data_table)

select @variable=column_name
from data_table

差异2:如果查询(query)不返回任何值,set把变量的值设置为NULL,而select将不会执行赋值操作,变量保持原来的值不变

--if query returns no value, assign variable null
set/select @variable=(select top 1 column_name from data_table)

--if query returns no value , the variable keeps previous value
select @variable=column_name
from data_table

代码中,查询(query)返回标量值,使用set和select对变量赋值,变量的值都是NULL

时间: 2024-08-10 15:11:35

不再迷惑,无值和NULL值的相关文章

【温故而知新-Javascript】比较 undefined 和 null 值

JavaScript 中有两个特数值: undefined和null,在比较它们的时候需要留心.在读取未赋值的变量或试图读取对象没有的属性时得到的就是 undefined 值. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Learn4UndefinedAndNull</title> </head

Sql与oracle中null值的区别

原贴链接请点击: 1 null值的介绍 NULL 是数据库中特有的数据类型,当一条记录的某个列为 NULL ,则表示这个列的值是未知的.是不确定的.既然是未知的,就有无数种的可能性.因此, NULL 并不是一个确定的值. 这是 NULL 的由来.也是 NULL 的基础,所有和 NULL 相关的操作的结果都可以从 NULL 的概念推导出来. 2 oracle中的null值介绍 在不知道具体有什么数据的时候,即未知,可以用NULL, 称它为空,ORACLE中,含有空值的表列长度为零.允许任何一种数据

set ANSI_NULLS 选项和Null值比较

强烈推荐:将选项 ANSI_NULLS 设置为On,在与Null值比较时使用 is null 或 is not null 查看和设置该选项的值 SET ANSI_NULLS ON --SET ANSI_NULLS OFF DECLARE @ANSI_NULLS VARCHAR(3) = 'OFF'; IF ( (32 & @@OPTIONS) = 32 ) SET @ANSI_NULLS = 'ON'; SELECT @ANSI_NULLS AS [ANSI_NULLS Option]; Whe

【Javascript 基础】比较 undefined 和 null 值

JavaScript 中有两个特数值: undefined和null,在比较它们的时候需要留心.在读取未赋值的变量或试图读取对象没有的属性时得到的就是 undefined 值. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Learn4UndefinedAndNull</title> </head

MySQ学习笔记之十 NULL值处理

这是MySQL一大特殊之处. 概念上,NULL意味着"没有值"或"未知值",且它被看作有点与众不同的值.为了测试NULL,你不能使用算术比较运算符例如=.<或!=.为了说明它,试试下列查询: mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL; +----------+-----------+----------+----------+ | 1 = NULL | 1 != NULL |

oracle 中的round()函数、null值,rownum

round()函数:四舍五入函数 传回一个数值,该数值按照指定精度进行四舍五入运算的结果. 语法:round(number[,decimals]) Number:待处理的函数 Decimals:精度,默认为0: Select round(123.456,0) as a,round(123.456,1) as b,round(123.456,-1) as c from dual; null值: NULL值就是没有值或者缺值.允许NULL值的列也允许在插入行时不给出该列的值.不允许NULL值的列不接

mysql null 值查询问题

我在开发公司内部的一个项目时遇到一个问题:select student_quality_id from STUDENT_QUALITY where mark_status=0 and batch_stauts in (2,3)结 果遇到一直找不到符合条件的student_quality_id ,后来才发现没有考虑到null值的问题,修改成 select student_quality_id from STUDENT_QUALITY where (mark_status=0 or mark_sta

Javascript中null值,特别注意的两点

null 是一个javascript字面量,表示空值,就是没有对象被呈现.他是javascript原始值之一.null值常被放在期望一个对象上,但是不引用任何对象的参数位置,也就是说对象的初始化. 我们看下面的一个例子 Javascript var obj = null; console.log(typeof obj === "object"); // true 我们通过对null的命名描述来理解,null是被期望在一个对象上,可能在javascript的规范中设这么设定的.所以返回一

Access空字符串和Null值

什么是空字符串和Null值: Microsoft Access可以区分两种类型的空值.因为在某些情况下,字段为空,可能是因为信息目前无法获得,或者字段不适用于某一特定的记录.例如,表中有一个“电话号码”字段,将其保留为空白,可能是因为不知道顾客的电话号码,或者该顾客没有电话号码.在这种情况下,使字段保留为空或输入Null值,意味着“不知道”.双引号内为空字符串则意味着“知道没有值”.采用字段的“必填字段”和“允许空字符串”属性的不同设置组合,可以控制空白字段的处理.“允许空字符串”属性只能用于“