1.NULL意思为缺失的值(missing value).

2.三值逻辑(three-valued-logic: TRUE,FALSE,UNKNOWN). 在SQL中有三个逻辑谓词:TURE,FALSE,UNKNOWN.在大多数的编程语言中只有TRUE和FALSE,而在SQL中独有UNKNOWN,之所有存在与NULL有关.

  比如做如下比较: NULL>32;NULL=NULL;X+NULL>Y;NULL<>NULL.其计算结果均为UNKNOWN.

  可能会有些迷惑,于二值逻辑不同(NOT TURE=FALUSE;NOT FALSE=TRUE)的是NOT UNKNOWN=UNKNOWN.

3.UNKNOWN作为FALSE时的处理. 在SQL中查询过滤时(ON,WHERE,HAVING)会把UNKNOWN作为FALSE处理,这样就不会把计算值为UNKNOWN的行添加到下一个结果集中.

4.UNKNOWN作为TRUE时的处理. 在CHECK约束中UNKNOWN却作为TRUE来处理.

5.再谈NULL与NULL的比较,上面已经讲过(NULL=NULL;NULL<>NULL),即NULL与NULL的比较均为UNKNOWN. 但是对于UNIOUE约束,集合操作(如UNION,EXCEPT),排序,分组时,NULL与NULL为认为是等值的.

关于SQL Server的Null值的比较运算的。一般情况下我们查询空值或者非空值的时候,用的是is null/is not null,而很少用=/<>。但是在我的这个程序中,没有用is这样的关键字,而是用=/<>这样的比较元算符号,这就碰到了一些问题。
问题起源于一个Web查询页面,因为问题比较复杂的,所以简化一下来说明。
在页面上用户可以自由选择数据表的某些字段,填写该字段的查询条件,先是选择比较运算符号(=,<>等),然后填写值。提交之后,就需要创建一个SQL语句,查询条件的各部分由不同的程序模块创建。这里涉及两个程序模块,一个模块根据提交创建比较运算符号,一个模块负责创建比较值模块。在创建值模块中有这样一个规则,“如果提交的值是空的,把该值设为Null”。
但是我发现,如果比价值为Null的时候,同样一个SQL查询语句放在存储过程里边查询和通过应用程序直接查询的结果是不一样的。
查了查SQL Server文档,发现Null值的比较运算,存在两种规则:
在SQL2000中Null值的比较运算有两种规则。一种是ANSI SQL(SQL-92)规定的Null值的比较取值结果都为False,既Null=Null取值也是False。另一种不准循ANSI SQL标准,即Null=Null为True。
以一张表T的查询为例。

表T存在下面的数据:
RowId Data
--------------
1 'test'
2 Null
3 'test1'

按照ANSI SQL标准,下面的两个查询都不返回任何行:
Query1: select * from T where Data=null
Query2: select * from T where Data<>null
而按照非ANSI SQL标准,查询1将返回第二行,查询2返回1、3行。
ANSI SQL标准中取得Null值的行需要用下面的查询:
select * from T where Data is null
反之则用is not null。由此可见非ANSI SQL标准中Data=Null等同于Data Is Null,Data<>Null等同于Data Is Not Null。

而控制采用那一种规则,需要使用命令SET ANSI_NULLS [ON/OFF]。ON值采用ANSI SQL标准,OFF值采用非标准模式。另外SET ANSI_DEFAULTS [ON/OFF]命令也可以实现标准的切换,只是这个命令控制的是一组符合SQL-92标准的设置,其中就包括Null值的标准。

默认情况下,数据库管理程序(DB-Library)是SET ANSI_NULLS为OFF的。但是我们的大多数应用程序,都是通过ODBC或者OLEDB来访问数据库的,作为一种开放兼容的数据库访问程序,或许是兼容性的考虑,SET ANSI_NULLS值设置为ON。这样一来带来的一些问题是需要注意的。像存储过程或者自定义函数这样的应用程序都是基于DB-Library的,默认情况下,SET ANSI_NULLS为OFF,并且在这样的程序中,不能使用SET ANSI_NULLS在一个环境中修改规则,只能修改数据库配置参数。

考虑下面这种情况。
你的应用程序使用ADODB来访问数据库,采用OleDb或者ODBC数据提供程序。对于前面的查询1:
select * from T where Data=null
你可以直接发送命令取得结果集,也可以把它放到存储过程当中。但是他们的查询结果是不一样的。如果直接使用查询命令,什么结果也没有,而如果访问存储过程,你获得第2行的数据。

我写了一个.Net程序来验证这一点。同时也为了验证.Net SqlClient的SET ANSI_NULLS的设置,由于SqlClient不是通过OleDb或者ODBC这些数据提供程序来访问SQL Server,而是直接对SQL Server进行访问,本来我以为它会采用SQL Server默认的设置,但是结果恰恰相反,它的默认设置和OleDb、ODBC一样。

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data.Odbc;
public class AnsiNullsTest{
public static void Main(String[] args){
IDbConnection conn;
String connType = "SqlClient";
if(args.Length>0)connType = args[0];
if(connType.ToUpper()=="OLEDB"){
Console.WriteLine("Connection Type:OLEDB");
conn = new OleDbConnection("Provider=SQLOLEDB.1;User ID=sa;PWD=test;Initial Catalog=TEST;Data Source=TEST");
}else if(connType.ToUpper()=="ODBC"){
Console.WriteLine("Connection Type:ODBC");
conn = new OdbcConnection("Driver={SQL Server};UID=sa;PWD=test;Database=TEST;Server=TEST");
}else{
Console.WriteLine("Connection Type:SQLClient");
conn = new SqlConnection("Server=TEST;Database=TEST;User ID=sa;PWD=test");
}
Test(conn);
}
public static void Test(IDbConnection conn){
String query1 = "select 'Test' where null=null";
String query2 = "exec p_Test"; //存储过程中是一样的SQL语句
IDbCommand cmd;
IDataReader reader;
Console.WriteLine("print 'Test' set ansi_nulls off");
try{
cmd = conn.CreateCommand();
conn.Open();
cmd.CommandText = query1;
reader = cmd.ExecuteReader();
Console.WriteLine("command:" + query1);
while(reader.Read()){
Console.WriteLine("result:" + reader[0].ToString());
}
reader.Close();
cmd.CommandText = query2;
reader = cmd.ExecuteReader();
Console.WriteLine("command:" + query2);
while(reader.Read()){
Console.WriteLine("result:" + reader[0].ToString());
}
reader.Close();
}
catch(Exception ex){
Console.WriteLine(ex.Message);
}
finally{
conn.Close();
}

}
}

它有一个参数,根据参数采用不同的参数值采用不同的数据库访问程序。命令对象作了两次查询,一次是SQL查询命令,一次是调用存储过程。语句都是一样,但是结果不一样。

SQL空和NULL的区别的更多相关文章

  1. 空字符串‘’ null false 区别

    1.''空字符串 .null 和false都是以值为0来存储的   只是数据结构不一致而已 空字符串------字符串数据格式 null -----------null数据格式 false ----- ...

  2. sql 中 '' 与 null 的区别

    SELECT * from t_company where content = '' SELECT * from t_company where content is null update t_co ...

  3. Django与SQL语言中——NULL与空字符串的区别

    SQL有指定空值的独特方式,它把空值叫做NULL. Null在数据库中表示 不知道的数据,主要有3种意思: 1)知道数据存在,但不知道具体值. 2)不知道数据是否存在. 3)数据不存在. 在SQL中, ...

  4. .NET和SQL Server中“空值”辨析 (DBNull与Null的区别)

    对表进行插入操作,如datetime和int类型的两个字段,都允许为null,用“sqlcmd.Parameters.Add("@t12",tb12.Text)”参数绑定时.dat ...

  5. SQL中IS NOT NULL与!=NULL的区别

    平时经常会遇到这两种写法:IS NOT NULL与!=NULL.也经常会遇到数据库有符合条件!=NULL的数据,但是返回为空集合.实际上,是由于对二者使用区别理解不透彻. 默认情况下,推荐使用 IS ...

  6. Java空字符串与null的区别和判断字符串是否为空的方法

    Java空字符串与null的区别: 1.类型null表示的是一个对象的值,而并不是一个字符串.例如声明一个对象的引用,String a = null ;""表示的是一个空字符串,也 ...

  7. SQL查询数据库表字段值不为空或Null的所有列

    ) set @TableName = 'Agency' -- 表名 declare @querySql nvarchar(max) set @querySql = 'select ' ) declar ...

  8. (七)修改上一条SQL语句,NULL值的滤空函数nvl

    修改上一条SQL语句 1.用c命令来修改(c 即 change ) 默认,光标闪烁位置指向上一条SQL语句的第一行.输入二则定位到第二行. c /错误的关键字/正确的关键字 SQL form emp; ...

  9. 【SQL Server 学习系列】-- SQL查询数据库表字段值不为空或Null的所有列

    ) set @TableName = 'Agency' -- 表名 declare @querySql nvarchar(max) set @querySql = 'select ' ) declar ...

随机推荐

  1. phpStorm配置SVN与FTP数据传输

    公司php开发时候,需要搭建环境,自己捋了下思路,公司代码放在SVN服务器上,需要在本机安装TortoiseSVN软件,将代码下载到本机,在本机上调试程序,修改代码,修改的代码再上传到SVN.之后通过 ...

  2. Win10桌面图标无法拖动

    1.右键桌面>查看>取消自动排列 2.桌面多按几次Esc 3.gpedit.msc  “用户配置/管理模板/Windows组件/任务计划程序/禁止拖放>改为未配置

  3. yum 安装和卸载

    yum list列出资源库中特定的可以Linux Yum安装或更新以及已经安装的rpm包 安装 yum install 安装包关键字 卸载 yum remove 安装包名

  4. AI 的下一个重大挑战:理解语言的细微差别

    简评:人类语言非常博大精妙,同一句话在不同的语境下,就有不同的含义.连人类有时候都不能辨别其中细微的差别,机器能吗?这就是人工智能的下一个巨大挑战:理解语言的细微差别.本文原作者是 Salesforc ...

  5. iOS学习笔记(5)——显示简单的TableView

    1. 创建工程 创建一个新的Xcode工程命名为SimpleTableTest. 删除main.storyboard文件和info.plist中有关storyboard的相关属性. 按command+ ...

  6. PHP和javascript中url编码解码详解

    在实际开发中,我们可能会遇到路径编码解码的问题,下面总结了一下: PHP中: 1.urlencode(编码),urldecode(解码) $a = urlencode('http://www.baid ...

  7. Win10将用户名修改为英文

    前言 最近重装了一次Win10系统,手贱地在引导里设置了中文的用户名.使用微软账户进行登录后,Win10以这个中文名建立了用户的文件夹,使得少数软件安装或使用过程中,保存路径不支持中文路径,从而报错, ...

  8. 【转载】基于Redis实现分布式锁

    背景在很多互联网产品应用中,有些场景需要加锁处理,比如:秒杀,全局递增ID,楼层生成等等.大部分的解决方案是基于DB实现的,Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端 ...

  9. 架构师养成记--26.vi/vim相关操作

    vi/vim命令模式插入模式 aio编辑模式 : aio就是vi/vim的插入模式命令    作用a         在光标后附加文本A         在本行末附加文本i         在光标钱插 ...

  10. v-bind、v-on 的缩写

    Vue中的缩写:v-bind.v-on v-bind 缩写:: 预期:any (with argument) | Object (without argument) 参数:attrOrProp (op ...