其他分享
首页 > 其他分享> > NULL与三值逻辑

NULL与三值逻辑

作者:互联网

文章目录

小结

三值逻辑含义

通常逻辑只有 真假(true / false), 如 java / c 等程序, 三只逻辑指的是逻辑有三个值: true / false / unknown(未知)

背景

关于SQL是否应该允许NULL,有很大争议

两派的意见

主张使用的原因

不主张使用的原因

最终 NULL 还是保留了下来

T-SQL 标准

3 + NULL = NULL; 10 * NULL = NULL; 10 / NULL = NULL

3 >= null 值为 unknown ; 3 =< null 值亦为 unknown

-- null 与值进行比较操作, 结果是 unknown
select 1 where 1=NULL
select 1 where 1<>NULL

-- NULL 与值进行运算操作, 结果是 NULL
select 1 where 1+NULL >= 1
select 1 where 1+NULL <= 1

千万不要用 等号 (=) 来判断一个值是否为 NULL, 想想为什么

建议

定义表结构时, 尽量使用 NOT NULL 约束

在使用NULL时,一定要搞清楚三值逻辑和数据库引擎对NULL的处理

MSSQL 对 null 的处理

ANSI_NULLS

SET ANSI_NULLS { ON | OFF }

指定在 SQL Server 2017 中与 Null 值一起使用等于 (=) 和不等于 (<>) 比较运算符时采用符合 ISO 标准的行为。

当 ANSI_NULLS 为 ON 时,即使 column_name 中包含空值,使用 WHERE column_name = NULL 的 SELECT 语句仍返回零行。 即使 column_name 中包含非空值,使用 WHERE column_name <> NULL 的 SELECT 语句仍返回零行。
当 ANSI_NULLS 为 OFF 时,等于 (=) 和不等于 (<>) 比较运算符不遵守 ISO 标准。 使用 WHERE column_name = NULL 的 SELECT 语句返回 column_name 中包含空值的行。 使用 WHERE column_name <> NULL 的 SELECT 语句返回列中包含非空值的行。 此外,使用 WHERE column_name <> XYZ_value 的 SELECT 语句返回所有不为 XYZ_value 也不为 NULL 的行。
当 ANSI_NULLS 为 ON 时,所有对 null 值的比较均取值为 UNKNOWN。

SET ANSI_NULLS (Transact-SQL)

练手

/*
create database Test
go

use Test
go

drop table tUser
go

create table tUser
(
    sID nvarchar(40) not null,
    sUserNO nvarchar(20) null,
    sUserName nvarchar(40) null,
    sPassword nvarchar(40) null,
    dLastUpdateTime datetime not null
)


insert into tUser
        (sID, sUserNO, sUserName, sPassword, dLastUpdateTime)
values  (newid(), null, 'test01', '', getdate()),
        (newid(), null, 'test02', null, getdate()),
        (newid(), 'userno01', 'test03', null, getdate()),
        (newid(), 'userno02', 'test04', null, getdate())

select * from tUser
*/

-- null 与值进行运算操作, 结果是null
select null + 10, 10 - null, null * 10, null / 10

-- 在where/on/having和if/case when中,三值逻辑中只有True才使条件成立
select *
from tUser as u
where u.sUserNO = ''

select *
from tUser as u
where u.sUserNO <> ''

-- group by 时,所有NULL被视为一组
select u.sUserNO, num = count(1)
from tUser as u
group by u.sUserNO

-- 聚集函数(SUM/AVG/MAX/MIN/COUNT)忽略NULL的行
select u.sUserNO, userNum = count(sUserNO), num = count(1)
from tUser as u
group by u.sUserNO

-- order by时, 所有NULL排在一起, 但NULL排在非空值的前面(如SQL Server)还是后面(如Oracle),SQL标准未规定
select *
from tUser as u
order by u.sUserNO

-- not 与 in / not in
-- not in (null, ...) 结果会变得意外, 故谨慎使用 not in + 子查询
select * from tUser where sUserNO in ('userno01')
select * from tUser where sUserNO not in ('userno01')

select * from tUser where sUserNO in ('userno01', null)
select * from tUser where sUserNO not in ('userno01',null)

参考

书籍: Microsoft SQL SERVER 2008技术内幕 T-SQL查询 : 1.3 逻辑查询处理阶段详解 (第九页)

标签:sUserNO,tUser,逻辑,null,三值,NULL,where,select
来源: https://blog.csdn.net/weixin_43324335/article/details/88093585