转自:http://blog.163.com/mig3719@126/blog/static/285720652010950921286/

7. 数据类型

在数据库理论中,关系模型和数据类型这两部分内容是正交的(参看《程序员修炼之道》第 8节关于“正交性”的讨论),互不依赖。换言之,关系模型并不关心每个表的字段的数据类型是什么,是整数、字符串等基本类型也好,是组合类型、类等自定义 类型也好,关系模型只要求每个字段是原子的。

在数据库理论中,数据类型又被称为域,但域是更为严格的定义。比如一个班级的学生个数和学生 平均分可能都是int类型,但这是两个不同的域,“学生个数 * 学生平均分 = 学生总分”,但“学生个数 + 学生平均分”是没有意义的。目前的主流DBMS似乎尚未对域有很好的支持,但未来的情况可能会有所改变,而且,设计自定义类型也需要对这一问题有充分的认 识。详见《深度探索关系数据库》第2章。

对于数据库和SQL的应用来说,除掌握关系模型的原理,还需要对DBMS支持的数据类型及其转换规则有所认识。

1. 基本数据类型

一个DBMS通常都会支持以下几类基本数据类型(以SQL Server为例):
- 精确数字:整数(bigint/int/smallint/tinyint/bit),定点小数(decimal),货币(money/smallmoney)
- 近似数字:浮点数(float)
- 日期和时间:datetime/smalldatetime; date, time, datetime2, datetimeoffset(后4种为SQL Server 2008的新增类型)
- 字符串和Unicode字符串:varchar/nvarchar, char/nchar(text/ntext已不再建议使用,用varchar(max)/nvarchar(max)代替)
- 二进制串(即字节流):varbinary, binary(image已不再建议使用,用varbinary(max)代替)
- 其他数据类型:具有特殊功能的类型(sql_variant, timestamp, uniqueidentifier, xml),不能用于表的特殊类型(cursor, table)

2. 关于数据类型需要注意的问题

a. 两类特殊的数据类型
- 日期和时间类型的数据存储方式和可用值范围、相关的计算、比较、显示(转换为指定格式的字符串)都比较复杂,还涉及一组日期时间函数。参看datetime类型分析一帖。
- 字符串类型涉及到字符编码和排序规则,比较操作还包含LIKE匹配(未来还可能会支持正则表达式匹配),非常需要注意。参看理解字符编码SQLServer中文处理二帖。

b. 如果对不同排序规则的两个字符串进行计算或比较,将会根据排序规则优先顺序来决定计算结果的排序规则或比较的方法。

c. 如果对不同类型的两个值进行计算或比较,将会根据数据类型优先级进行隐式转换。数据类型优先级基本规则如下:
- 大 > 小(>指优先级高于,下同):如bigint > int > smallint > tinyint > bit,varchar(20) > varchar(10),datetime > smalldatetime,等等。
- 可变 > 固定:如float > decimal,varchar > char,nvarchar > nchar,varbinary > binary。
- 各类型大类的优先级:datetime > float > decimal > integer > unicode string > ansi string > binary。
- 特殊数据类型的优先级和转换规则需要特殊考虑,详见联机丛书。

d. 如果对不同大小的两个值进行计算,将会根据精度、小数位数和长度的规则来产生新的类型大小。

e. 常量的数据类型(可以通过SELECT col = 常量值 INTO testdt然后查看testdt表col字段的数据类型来观察)
- 如果不显式指定和隐式转换,NULL会按int类型处理。
- '', N'', 1, 0x01, 1.0, 1E0, $1分别对应varchar, nvarchar, int, varbinary, decimal, float, money类型,并且长度是存储相应值所需要的最小长度。

f. 在软件开发领域众所周知:“隐式转换是bug的源泉”。因此,有两个建议:
- 使用常量时,最好使用对应类型的常量。比如,如果table.col是varchar类型,那么WHERE table.col = 10的查询将不能使用索引,而且当遇到col中存放有不能转换为数字的值时将出错。
- 除非相应值的隐式转换非常直观,否则宁可用CAST()/CONVERT()指定明确的显式转换。

以上内容中,加下划线的粗体是联机丛书的标题。详细分析参看《Microsoft SQL Server 2005技术内幕:T-SQL程序设计》第1章。

8. NULL与三值逻辑

三值逻辑(3VL, Three-valued Logic)绝对是SQL修炼中的一个紧要关卡,值得特别注意,闭关静修。待冲破这一关卡之后,SQL中的NULL与NOT NULL将别无二致。

关于SQL是否应该允许NULL,在数据库领域已经近乎一个信仰式的争论。E.F.Codd认为NULL有存在的必要,但他的好友C.J.Date认为NULL完全可以取消。最终结果是,SQL标准支持NULL。

理论上的争论且不管。但在实践中,一定要知道NULL的三值逻辑会带来很多困扰的问题。
a. 不使用NULL的理由:
- NULL会引入复杂的三值逻辑。
- NULL在查询条件、外键和CHECK约束、唯一约束、GROUP BY、ORDER BY中的行为都是不一致的。
b. 使用NULL的理由:
- 当需要表示一个未知的、不确定的值时,用NULL更自然。比如一个现在职员工的离职时间、顶级员工(BOSS)的上级员工,等等。
- 外联接通常会引入NULL,即使所有表的字段都定义为NOT NULL。

首先,如果可能,尽量让所有字段都声明为NOT NULL。除非是更适合使用NULL的场合(从业务出发)。

其次,在使用NULL时,一定要搞清楚三值逻辑和数据库引擎对NULL的处理:
(SQLServer有一个选项SET ANSI_DEFAULTS,默认为ON,即与SQL标准一致。设为OFF的效果详见联机丛书。)

1. NULL与别的值进行+-*/等计算操作(包括在大多数函数中使用NULL)后,结果是NULL(标量表达式)。NULL与别的值进行=、>、<等比较操作后,结果是Unknown(断言)。
Unknown相关的逻辑运算:
[code=sql] 
NOT Unknown --> Unknown 
Unknown AND/OR Unknown --> Unknown 
Unknown OR TRUE --> TRUE 
Unknown AND TRUE --> Unknown 
Unknown OR FALSE --> Unknown 
Unknown AND FALSE --> FALSE 
[/code]
具体可查三值逻辑的真值表。

2. 在where/on/having和if/case when中,只有True才使条件成立(即Unknown当作False来处理)。比如:
where column = value:表中column为NULL的行永远不会返回,即使value是NULL;
case value when NULL then XXX when ... end:XXX永远不会执行,即使value是NULL;
if <Unknown> XXX else YYY end或case when <Unknown> then XXX else YYY end:这两种情况下,YYY会执行。

3. 包含外键约束和Check约束的字段允许NULL(即约束只当条件为False时出错,Unknown是不管的)。
4. 包含唯一约束(unique index)的字段只允许一个NULL的行,再插入或更新该字段为NULL的行会报字段重复的错误。
5. GROUP BY时,所有NULL被视为一组。
6. ORDER BY时,所有NULL排在一起,但NULL排在非空值的前面(如SQL Server)还是后面(如Oracle),SQL标准未规定。
7. 聚集函数(SUM/AVG/MAX/MIN/COUNT)忽略NULL的行。
8. declare的变量,在未赋值之前为NULL。
9. 与NULL处理相关的运算符和函数:
- IS NULL/IS NOT NULL:用这两个运算符来判断一个值是否为NULL,而不是=或<>。
- ISNULL/COALESCE:取第一个非空值(注意两个函数的数据类型转换规则不同)。
- NULLIF(a,b):等价于CASE WHEN a = b THEN NULL ELSE a END。

Trackback : http://topic.csdn.net/u/20100826/18/7b81012a-b5c4-48b1-b5d1-40a92f3e0388.html

转:如何学习SQL(第三部分:SQL数据类型与三值逻辑)的更多相关文章

  1. opencv学习笔记(三)基本数据类型

    opencv学习笔记(三)基本数据类型 类:DataType 将C++数据类型转换为对应的opencv数据类型 OpenCV原始数据类型的特征模版.OpenCV的原始数据类型包括unsigned ch ...

  2. python学习之第三课时--基本数据类型及区别,变量

    基本数据类型及区别 1. 数字类型(int) 数字型--变量值直接是数字,没有双引号""   整数 2. 浮点数(float) 肤浅理解小数点后有有效数字  1.55  0.22 ...

  3. MyBatis学习总结(三)——多表关联查询与动态SQL

    在上一章中我们学习了<MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射>,这一章主要是介绍一对一关联查询.一对多关联查询与动态SQL等内容. 一.多表关联查询 表与 ...

  4. sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)

    sql server 关于表中只增标识问题   由于我们系统时间用的过长,数据量大,设计是采用自增ID 我们插入数据的时候把ID也写进去,我们可以采用 关闭和开启自增标识 没有关闭的时候 ,提示一下错 ...

  5. MySQL数据库学习笔记(三)----基本的SQL语句

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  6. Mybatis学习系列(三)动态SQL

    在mapper配置文件中,有时需要根据查询条件选择不同的SQL语句,或者将一些使用频率高的SQL语句单独配置,在需要使用的地方引用.Mybatis的一个特性:动态SQL,来解决这个问题. mybati ...

  7. 第三篇 SQL Server安全主体和安全对象

    本篇文章是SQL Server安全系列的第三篇,详细内容请参考原文. 一般来说,你通过给主体分配对象的权限来实现SQL Server上的用户与对象的安全.在这一系列,你会学习在SQL Server实例 ...

  8. 数据库学习笔记 4 强大的SQL

    其实这篇文章应该至少一个星期前就应该更新了,但是最近小猿我和喜欢了好多年的女神牵手成功,所以这些天有点飘. ---创建表结构 create table tablename ( id int, name ...

  9. 大数据技术之_19_Spark学习_03_Spark SQL 应用解析 + Spark SQL 概述、解析 、数据源、实战 + 执行 Spark SQL 查询 + JDBC/ODBC 服务器

    第1章 Spark SQL 概述1.1 什么是 Spark SQL1.2 RDD vs DataFrames vs DataSet1.2.1 RDD1.2.2 DataFrame1.2.3 DataS ...

  10. 【译】第三篇 SQL Server安全主体和安全对象

    本篇文章是SQL Server安全系列的第三篇,详细内容请参考原文. 一般来说,你通过给主体分配对象的权限来实现SQL Server上的用户与对象的安全.在这一系列,你会学习在SQL Server实例 ...

随机推荐

  1. JAVA基础知识之多线程——线程池

    线程池概念 操作系统或者JVM创建一个线程以及销毁一个线程都需要消耗CPU资源,如果创建或者销毁线程的消耗源远远小于执行一个线程的消耗,则可以忽略不计,但是基本相等或者大于执行线程的消耗,而且需要创建 ...

  2. 2016-2017 CT S03E05: Codeforces Trainings Season 3 Episode 5 (2016 Stanford Local Programming Contest, Extended) J

    链接:http://codeforces.com/gym/101116 题意:给出n个点,要求一个矩形框将(n/2)+1个点框住,要面积最小 解法:先根据x轴选出i->j之间的点,中间的点(包括 ...

  3. qbxt十一系列三

    [题目分析] 这完全是个数学题啊,有些崩溃,上午考试写了两个小时,20分,于是乎 下午改啊改啊 改到10分....如果第二个圆的圆心在第一个圆.....呃 说不清楚 像下面这个图这样,两圆重叠部分中C ...

  4. zookeeper系列之四—coordinate

    http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html

  5. MySQL的存储过程1

    来源:http://blog.sina.com.cn/s/blog_52d20fbf0100ofd5.html MySQL的存储过程 2. 关于MySQL的存储过程存储过程是数据库存储的一个重要的功能 ...

  6. 1-NPM

    什么是NPM NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题. 常见的使用场景有以下几种: 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从N ...

  7. C#无需IIS构建XmlRpc服务器

    准备 我们使用CookComputing.XmlRpcServerV2 3.0.0来构建XmlRpc服务器. 新建一个控制台项目,在项目中添加对CookComputing.XmlRpcServerV2 ...

  8. [HDOJ3709]Balanced Number(数位dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709 题意:求区间[L,R]内每一个数中是否存在一位,使得左边的各位数*距离=右边的各位数*距离(自己 ...

  9. 安全漏洞API接口

    这个是avfisherapi写的API,经常用,每次找他的博客都搜到AV,尴尬..在这里记下来. 0x01 查询最新安全事件和漏洞的接口 接口URL: 乌云网: http://avfisherapi. ...

  10. Sencha Toucha之Ext.Ajax

    Ext.Ajax是Ext.data.Connection的hi一个单实例,不需要使用new或者Ext.create方法创建实例后再使用. 类的继承关系为: Ext.Base Ext.data.Conn ...