zoukankan      html  css  js  c++  java
  • TSQL--NULL值和三值逻辑

    在SQL SERVER 中逻辑表达式存在三种值:TRUE+FALSE+UNKNOWN。UNKNOW可以理解为不确定,既不是TRUE又不是FALSE的表达式,主要由与NULL相关的逻辑判断引起,值为NULL就意味着该未赋值或该值未确定。

    与NULL值做算术运算时,其结果是NULL,如果1+NULL结果为NULL

     

    SQL Server不同场景下对UNKNOWN处理不同,对NULL的处理也不同。

    1. 在WHERE+ON+HAVING三种筛选器中,所有运算结果非TURE(FALSE 与UNKNOW)的记录都不会返回;

    2. 在CHECK约束中,所有运算结果为非FALSE(TRUE与UNKNOW)的都属于满足CHECK约束的;

    3. 在UNIQUE约束中,如果列定义未限制为NOT NULL,那么允许该列存在一条NULL值,如果另外插入或更新一条记录为NULL时,会违法UNIQUE约束,NULL与NULL是相等的;

    4. 在GROUP BY中,NULL值被认为相同而分为一组,NULL与NULL是相等的;

    5. 在ORDER BY中,NULL值被认为相同而排列在一起,所有NULL值比已知值小,NULL与NULL是相等的;

     

    除上述3/4/5条中提到的情况外,NULL与NULL是不相等的。

    默认情况下,即SET ANSI_NULLS ON时,对于条件(WHERE C1 = NULL)这种查询,C1列值为NULL的行不会被返回;

    而当SET ANSI_NULLS ON时,对于条件(WHERE C1 = NULL)这种查询,C1列值为NULL的行会被返回,此时C1=NULL应该被理解为做C1 IS NULL 运算,而不应该理解为NULL与NULL相等;

    理解混乱的同学可以做以下测试:

     

    --==========================================
    --生成测试数据
    DECLARE @TB TABLE
    (
        C1 INT
    )
    
    INSERT INTO @TB
    SELECT 1
    UNION
    SELECT NULL
    
    --===========================================
    --修改默认选项值,设置ANSI_NULLS
    --注意该设置是回话级别,而不是批处理级别或语句级别
    SET ANSI_NULLS OFF;
    
    --============================================
    --当ANSI_NULLS OFF时,C1=NULL 等同于C1 IS NULL
    --因此查询返回一条NULL的记录
    SELECT * FROM @TB
    WHERE C1=NULL
    
    --============================================
    --当ANSI_NULLS OFF,NULL与NULL仍不认为相等
    --因此查询中不会返回NULL的记录
    SELECT * FROM @TB AS TB1
    INNER JOIN @TB TB2
    ON TB1.C1=TB2.C1

    运行结果为:

    为规范操作和避免混乱,强烈建议使用IS NULL 和IS NOT NULL判断值是否为NULL,避免修改默认选项ANSI_NULLS为OFF。

     

    除上面提到的特殊情况外,由于NULL与NULL是不相等的,因此

    1. 在做IN和EXISTS运算如WHERE C1 IN(SELECT ID FROM TB1) 或者 WHERE EXISTS (SELECT ID FROM TB1 WHERE ID =C1)时,所有C1列为NULL的行都不会被返回,无论表TB1的ID列是否存在NULL值;

    2. 对NOT IN运算如T1.C1 NOT IN (SELECT T2.C1 FROM T2) 时,如果表T2的C1列存在NULL值, 那么查询将不会返回任何记录,无论表T1的C1列是否有NULL值存在。

    3. 对NOT EXISTS运算如NOT EXISTS(SELECT C1 FROM T2 WHERE T2.C1=T1.C1),会返回T1表有但T2表没有且T1.C2 IS NOT NULL的记录

    测试DEMO

    --=================
    --生成测试数据
    DECLARE @TB TABLE
    (
        C1 INT
    )
    
    DECLARE @TB2 TABLE
    (
        C1 INT
    )
    
    
    INSERT INTO @TB
    SELECT 1
    UNION
    SELECT 2
    
    
    INSERT INTO @TB2
    SELECT 1
    UNION
    SELECT NULL
    
    --=================================
    --NOT EXISTS返回记录为2的行
    SELECT * FROM @TB AS TB1
    WHERE NOT EXISTS(
        SELECT C1 FROM @TB2 AS TB2 
        WHERE TB2.C1=TB1.C1)
    --================================
    --NOT IN 不返回任何行
    SELECT * FROM @TB
    WHERE C1 NOT IN
    (
        SELECT C1 FROM @TB2
    )
    View Code

     

    因此,IN和EXIST可以相互改写,但是NOT IN不能随便改写为NOT EXISTS.

     

    PS: 对于运算结果为UNKNOW的逻辑表达式,再做NOT运算,结果仍未UNKNOW

     --==========================================================

    妹子振贴

  • 相关阅读:
    HDU2515_数学规律题
    HDU1086_You can Solve a Geometry Problem too_判断两线段相交
    HDU1115_Lifting the Stone_凹凸多边形重心_可作为模板
    HDU2036_改革春风照大地_点求多边形面积
    Codeforces Beta Round #92 (Div. 2 Only) _A题
    HDU2108_Shape of HDU_判断凹凸
    response.setContentType设置
    vue 文件下载实现
    iText5实现Java生成PDF文件完整版
    java使用IText将数据导出为pdf文件(数据为excel表格样式)
  • 原文地址:https://www.cnblogs.com/TeyGao/p/3519557.html
Copyright © 2011-2022 走看看