对于设计和创建数据库完全是个新手?没关系,Joe Celko, 世界上读者数量最多的SQL作者之一,会告诉你这些基础。和往常一样,即使是最专业的数据库老手,也会给他们带来惊喜。Joe是DMBS杂志是多年来最受 读者喜爱的作者。他在美国、英国,北欧,南美及非洲传授SQL知识。他在ANSI / ISO SQL标准委员会工作了10年,为SQL-89和SQL-92标准做出了杰出贡献。


对于数据库开发人员,SQL数据类型和域的清楚了解是基本要求,但不是基础。如果你选择了最合适的数据类型,它可以避开很多错误。此外,然后如果你通过约束尽可能精确的定义数据域,你会捕获各种这样的问题,那就是否则会困扰应用开发人员的工作。

第1篇,我们为它们是什么而命名数据元,并为它们分类。因此现在我们知道,我们不能用通用的,神奇的,普遍的“id”作为数据元。它必须是一个在架构里有确切含义的确切名称。更好的是,名称应该是企业范围,行业范围或在全球的优先排序里。

在第2篇里,我们会决定通过选择合适的域把那些数据放入计算机。域的想法要回到Codd博士。嗯,实际上在这个好博士(Good Doctor)之前,因为它来自数学。域像程序设计里的数据类型,但涉及更多。域有合法的在它的值上完成的运算符,除此之外还有一个数据类型。例如,我可以使用INTEGER在数据库里记录温度;那是个数据类型。当我看到100,那是个值。同时,我可以加,减,乘和除整数,但在温度上这样做没有意义。你不能把体温是36°的人放一起来烧水。模型的类型决定允许什么操作。但我需要知道数字是否以华氏度(Fahrenheit (°F)),摄氏度(Celsius (°C))还是绝对温度(Kelvin (°K));那是计量单位。把这些放在一起,你就有了域。

标准SQL有CREATE DOMAIN语句,它创建的架构对象不是真正的域。它只是个我们即将讨论的缩写。

SQL有3大类数据类型:

  1. 数值(Numberic)
  2. 字符串(String)
  3. 日期(Temporal)

数值型分为精确和近似的。精确数值有INTEGER, SMALLINT, DECIMAL, NUMERIC和BIGINT。它们保存精确的数值并有明确的计算运算符。近似数值有REAL, FLOAT 和 DOUBLE PRECISION(双精度)。这些是浮点数,它们会有四舍五入的问题;近来IEEE浮点标准普遍使用。SQL里也不例外;大多数其它可以进行计算的编程语言使用全部,或者使用这些类型的一些,因为它们在SQL 发明很早以前就嵌入了计算机硬件。PC和迷你计算机用户很可能不知道二进码十进制(BCD(Binary Coded Decimal))数,但多年来它们是商业电脑主机的组成部分。如果你不能理解这些类型,可以google下它们。

字符串类型分为定长和变长。定长字符串是CHAR (n) 和NCHAR(n),这里(n)是它们的长度。NCHAR(n)是“National Character”的简称,它的真正含义是来自Unicode已经实行的任何语言的任何字符。CHAR (n) 是本地ASCII字符集。变长字符串不会像定长字符加个空白字符。对列选择长度和字符集是你在使用它之前,真的要考虑的约束。太短的列会阻止真正的数据,同时太长的列会引入虚假的数据。我最喜欢的一个技巧,当我看到一个以NVARCHAR(255)定义的列,用它来加载中文的心经。这是禅宗佛教(Zen Buddhism)的经典经文。如果我不能教他们SQL,我会带它们启蒙。

日期类型分为纯日期时间和间隔类型。日期时间类型分为日期和时间。它表示时间上一个点。日期类型包含年,月和日。时间类型包括时,分,秒和10进制的次秒。放一起,在标准SQL里它们组成TIMESTAMP数据类型,SQL Server称它们为DATETIME。间隔类型是像天,时,分和秒的时间持续。SQL Server不把它们作为特定类型来表示,使用整数的函数来得到类似结果。

对所有数据类型的四舍五入和截断实现定义。所有数据类型允许NULL,同时在SQL标准里,对所有的数据类型有一组核心的函数,提供所有有的属性扩展和细节实现。例如,SQL Server有BIT数据类型,它是一个精确的数字,只允许0, 1, NULL值。你也会找到更多的数据类型,但这“三个值”会完成你的大多数工作。

当你在数据上你要做计算时,使用数值类型。那就是说像数量,个数,合计等等数据元。如果你需要进行除简单加减外的计算,对于四舍五入和溢出定义一些额外的小数位。

对于要排序的嗲吗你也会使用数值类型。例子就是餐厅的星级(例如1星没有2星的好,2星的没有3星的好,以此类推)。不要为不进行计算或比较的尺度使用数值类型。这个错误的常见例子是邮编(ZIP code);第一个数字0有它的意思,你不能在它们上面进行计算,也不能进行排序。标签数用来表示层级。

对文本,名称和编码体系使用字符串可以用正则表达式表示。例如,邮政编码应该用CHAR(5)定义。不要尝试计算它们;在COBOL里可以,在SQL里不行。

对于日期数据使用日期数据类型。没错,听起来太明显,我都没必要说。但其中一个最常见的设计错误是对于日期和时间数据使用字符串。当然这样做的人不会写约束来阻止像“2010-02-31”的日期或者进行简单时间计算函数。他们已经犯了设计错误,把显示格式放入数据库,而不是前端。

实数和时间是连续的例子,其它数据类型是离散的。离散范围是任何两个不同值之间有限的数字(很可能0)。例如整数{4,9},在它们之间有{5,6,7,8}。有一期儿童电视节目iCarly里,女主持人说服另一个小孩,在5和6之间有一个叫Dirf的新的数字。这个笑话太滑稽了,因为很明显它是错误的。

连续性是数学结构,在任何两个不同值之间有无限个数据值。你总可以添加越来越多的小数到实数或没有任何限制的时间。浮点数有内建的功能来处理四舍五入和计算的问题,但是时间数据不行。通常这就是说你要用一对值来模式化事件(开始事时间,结束时间)。如果事件还是当前的,那么使用NULL作为结束事件值。然后在应用程序里你可以使用COALESCE()函数来转化NULL为CURRENT_DATE或其它有意义的值。

约束是表里的列像记录里的字段的一个原因。约束是在列里约束值的陈述句。最重要的一个是NOT NULL。首次用它来申明每列,然后如果你决定允许NULL,注释行申明来解释说明在上下文里的意思。例如:

sale_start_date DATE NOT NULL,
sale_end_date DATE, – sale is still in progress

CHECK(<涉及列的谓语>)是最简单的行级别约束。然和有效的谓语可以使用,一些典型的使用会是:

 sex_code SMALLINT NOT NULL
CHECK (sex_code IN (0,1,2,9)), body_temperature DECIMAL (3,1) NOT NULL
CHECK (body_temperature BETWEEN 0.0 AND 45.0), airport_code CHAR(3) NOT NULL
CHECK (airport_code = UPPER (airport_code)), zip_code CHAR(5) NOT NULL
CONSTRAINT Valid_ZIP_Code
CHECK (zip_code LIKE '[0-9][0-9][0-9][0-9][0-9]'),

你也可以命名约束,如上所示。这是个很好的做法,因为它让错误信息更容易阅读。使用CASE表达式你会得到很多有意思的东西,对于其它复杂规则使用if-then逻辑的其它谓语,例如:

 floob_score INTEGER CHAR(5) NOT NULL
CHECK (CASE WHEN floob_score NOT BETWEEN 1 AND 99 THEN 'F'
WHEN floob_score = 42
AND fuzz_nbr = 17
THEN 'T' ELSE 'F' END = T'),

作为练习,写一个CASE表达式来验证是否为数字。表达式会很长但不难。

除了数据完整性,约束还会为你做其它好事。优化器可以用到它们来提高你的查询,插入,更新和删除。它们帮你节约很多前端代码;在这里一次搞定,就不用在很多应用程序里反复做,不管现在还是将来。它们保证所有的前端程序使用同样定义的数据元。

CHECK()约束也可以放在表级别。例如:

sale_start_date DATE NOT NULL,
sale_end_date DATE, – sale is still in progress
CONSTRAINT Validate_Sale_Duration
CHECK (sale_start_date <= sale_end_date),

表约束涉及到两个或更多的列。在标准SQL里,你也可以有引用其它表的CHECK()约束,但现在我会跳过这个;它没有广泛应用,或不是SQL Server的组合。

SQL的策略是它我们用NULL进行比较时,逻辑值的结果是UNKNOWN,不是TRUE或FALSE。但在CHECK()约束里,TRUE和UNKNOWN同等对待。我们把质疑的好处给UNKNOW。

在行里定义里的最后选项是DEFAULT子句(默认值)。技术上来说它不是域定义的组成,它非常有用。在标准SQL里,它会在数据类型后立即出现,在行定义里,大多数对于它的放置位置都是自由的。它是个常量值或者调用合适数据类型的系统值。最常见的例子是,对于数字和字符串数据在编码架构里的默认值,对于日期数据的CURRENT_TIMESTAMP和CURRENT_DATE。例如ISO的性别编码使用0作为“未知”,1为”男性“,2为”女性“,9作为合法的人(lawful person )(企业和其它组织会在上下文里识别为”法人(legal persons)“)。例如,我们会像这样申明行:

 sex_code SMALLINT NOT NULL
DEFAULT 0
CHECK (sex_code IN (0,1,2,9)),
sale_start_date DATE DEFAULT CURRENT_DATE NOT NULL

默认值的目的是在没有直接给值的地方提供值。这通常使用INSERT INTO语句完成,在这里你必须构建整个行,但你不想暴露所有行给用户,或者你想节省一些编程工作。总是提供默认不太可能,当你有的时候再这样做。

现在我们会创建行,在第3篇里我们需要组合行到表里。那里我们约束的其它类型,它会应用到列,不止单行。

原文链接:

http://www.sqlservercentral.com/articles/Database+Design/69926/

数据库设计(2/9):域,约束和默认值(Domains, Constraints and Defaults)的更多相关文章

  1. [置顶] T-sql sql server 设置主键约束、标示列、唯一约束、默认值、约束、创建表

    ----选择数据库 use ythome go ----查看表是否存在 if Exists ( select * from sysobjects where name='sys_menu' and t ...

  2. SQL数据库之设置查询出来数据为默认值

    -- 如果工资为null,按0处理 -- 函数: ifnull(字段, 默认值) : 如果指定字段的内容是null, 就按默认值处理 select name, ifnull(salary, 0) fr ...

  3. 数据库设计mysql字段不默认为NULL原因搜集

    索引不会包含有NULL值的列 只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的.所以我们在数据库设计时不要让字段的默认值为NULL ...

  4. day39 python 学习 数据库学习 五个约束,数据库设计(一对一,一对多等等)

    删除重复数据:  注意数据库不能又查又删 *******#删除作者为重复数据并保留ID最大的是数据 delete from ren where author in (select * from(sel ...

  5. 优化MySchool数据库设计之【巅峰对决】

    优化MySchool数据库设计 之独孤九剑 船舶停靠在港湾是很安全的,但这不是造船的目的 By:北大青鸟五道口原玉明老师 1.学习方法: 01.找一本好书 初始阶段不适合,可以放到第二个阶段,看到知识 ...

  6. 约束Constraints--主键约束、外键约束、唯一约束、检查约束、默认约束、NOT NULL约束、列约束与表约束、创建约束、删除约束

    约束   Including Constraints 以下内容转自:https://www.cnblogs.com/wcl2017/p/7043939.html和http://blog.csdn.ne ...

  7. EF Core中,通过实体类向SQL Server数据库表中插入数据后,实体对象是如何得到数据库表中的默认值的

    我们使用EF Core的实体类向SQL Server数据库表中插入数据后,如果数据库表中有自增列或默认值列,那么EF Core的实体对象也会返回插入到数据库表中的默认值. 下面我们通过例子来展示,EF ...

  8. ADO.NET实体数据模型中关于数据库字段默认值的处理

    无论是Visual Studio 2010或者2013内置的ADO.NET实体数据模型都有一个小问题:数据库中有些字段已设置了默认值,但ADO.NET实体数据模型工具并不会自动进行设置. 这时需要手工 ...

  9. asp.net EF model中的默认值设置

    在做数据库规划时,通常会规划一些系统字段,也就是由数据库本身自行指定默认值到这个字段上,创建新的“创建时间(CreateDate)”字段就会常常这样设计. 如果希望能有默认值,且让.net 程序在新增 ...

随机推荐

  1. SQL——行值表达式(Row Value Expressions)

    概述 最近接触了一个新概念——行值表达式,也叫做行值构造器.这是一个很强大的SQL功能,通常我们所操作的SQL表达式都只能针对一行中的单一字段进行操作比较,而行值表达式可以针对一行中的多个字段进行操作 ...

  2. 初探XSS

    1. 基础准备知识 (1) php: <?php ?>部分由服务器解析后并连带html代码一并返回给浏览器,类似jsp的操作,一般开发中都使用smarty模板将前端后端分开.所以在XSS跨 ...

  3. sublime Text3及其插件的使用

    参考:Sublime Text 3 新手上路:必要的安裝.設定與基本使用教學 Sublime Text 相信是許多開發人員人心目中的最愛,然而對一個 Sublime Text 3 的新手來說,有什麼是 ...

  4. setprecision、fixed、showpoint的用法总结

    首先要加头文件:iomanip 一:setprecision 作用:控制输出流显示浮点数的数字个数,setprecision(n)就是输出的n个数,会有四舍五入. 比如:double s=20.784 ...

  5. for循环中的 else,break

  6. sqlalchemy(一)基本操作

    sqlalchemy(一)基本操作 sqlalchemy采用简单的Python语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型. 安装 需要安装MySQLdb pip install ...

  7. Android学习——windows下搭建Cygwin环境

    在上一篇博文<Android学习——windows下搭建NDK_r9环境>中,我们详细的讲解了在windows下进行Android NDK开发环境的配置,我们也讲到了在NDk r7以后,我 ...

  8. Azure PowerShell (5) 使用Azure PowerShell创建简单的Azure虚拟机和Linux虚拟机

    <Windows Azure Platform 系列文章目录> 本文介绍的是国外的Azure Global.如果是国内由世纪互联运维的Azure China,请参考这篇文档: Azure ...

  9. Atitit 索引技术--位图索引

    Atitit 索引技术--位图索引 索引在数据结构上可以分为三种B树索引.位图索引和散列索引 存储原理 编辑 位图索引对数据表的列的每一个键值分别存储为一个位图,Oracle对于不同的版本,不同的操作 ...

  10. kettle资源库配置

    资源库的作用:资源库是用来保存操作步骤和相关的日志,转换,JOB 等信息.用户通过图形界面创建的的转换任务可以保存在资源库中.资源库可以是各种常见的数据库,用户通过用户名/ 密码来访问资源库中的资源, ...