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. java—不同的用户登录以后可以看到不同的菜单(后台可以实现对用户菜单的管理) 1 (55)

    实现不同的用户登录以后可以看到不同的菜单.(后台可以实现对用户菜单的管理.) 第一步:分析数据结构        1:用户表 表名:users 列名 类型 说明 id Varchar(32) 主键 n ...

  2. 洛谷P3676 小清新数据结构题(动态点分治+树链剖分)

    传送门 感觉这题做下来心态有点崩……$RMQ$求$LCA$没有树剖快我可以理解为是常数太大……然而我明明用了自以为不会退化的点分然而为什么比会退化的点分跑得反而更慢啊啊啊啊~~~ 先膜一波zsy大佬 ...

  3. deepin配置反向代理映射本地到公网

    这里我是用的小米球的免费ngrok 相信deepin的新用户在配置反向代理时,会感觉到一脸茫然,因为一开始我也是这样,但经过短暂的了解了deepin后,发现,其实与在Debian上配置并没有什么区别! ...

  4. jquery 通过attr获取属性只有一个值的解决

    var a = []; $($('select.list[data-target="' + target + '"]').find("option:selected&qu ...

  5. verify验证插件的详解

    使用此验证插件,我们只需要新建一个实例对象,同时传入一个json对象就行了,这里我们只传入了两个属性:checkItem和callback.下面的代码解析,我们就按照这个例子来. var verify ...

  6. python 爬虫 黑科技

    1.最基本的抓站 import urllib2 content = urllib2.urlopen('http://XXXX').read() 2.使用代理服务器 这在某些情况下比较有用,比如IP被封 ...

  7. 老男孩Day12作业:RabbitMQ-RPC版主机管理程序

    一.作业需求 1.可以对指定机器异步的执行多个命令 例子: 请输入操作指令>>>:run ipconfig --host 127.0.0.0 in the call     tack ...

  8. mongodb 两台互为主从

    主机A [root@mysql_master zhxf]# cat docker-compose.yml version: '3' services: mongo_rs1: image: mongo: ...

  9. Spring集成ignite,服务发现问题

    问题: 解决办法: 修改C:\Windows\System32\drivers\etc\hosts 配置主机名和ip对应关系: 试试!

  10. 基础概念——理解IP地址和域名

    从程序员角度,可以把因特网看做是世界范围内的主机集合: 1)主机集合被映射为一组32位的IP地址. 2)这个IP地址被映射为一组称为因特网域名的标识符. 3)因特网主机上的进程能够通过连接和任何其他因 ...