个人笔记不保证正确。

数据类型是限制我们可以在表里存储什么数据的一种方法。不过,对于许多应用来说, 这种限制实在是太粗糙了。比如,一个包含产品价格的字段应该只接受正数。 但是没有哪种标准数据类型只接受正数。 另外一个问题是你可能需要根据其它字段或者其它行的数据来约束字段数据。比如, 在一个包含产品信息的表中,每个产品编号都应该只有一行。

对于这些问题,SQL 允许你在字段和表上定义约束。约束允许你对数据施加任意控制。 如果用户企图在字段里存储违反约束的数据,那么就会抛出一个错误。 这种情况同时也适用于数值来自默认值的情况。

1. 外键 FOREIGN KEY

外键约束声明一个字段(或者一组字段)的数值必须匹配另外一个表中出现的数值。

创建外键约束的前提是,该外键所在的表已经存在,并且外键必须是 UNIQUE 的。(主键默认 UNIQUE 且 NOT NULL)

CREATE TABLE <表名> (
<字段名> <类型> PRIMARY KEY,
<字段名> <类型> REFERENCES <外键所在的表名> (<字段名>), -- 这创建了一个外键
...
);

还有另一种语法,它支持以多个字段为外键(字段约束也可以写成表约束,也就是放在一个独立的行中。而反过来很可能不行):

CREATE TABLE <表名> (
<字段名1> <类型> PRIMARY KEY,
<字段名2> <类型>
<字段名3> <类型>
...
FOREIGN KEY (<字段名2>, <字段名3>) REFERENCES <外键所在的表名> (<字段名4>, <字段名5>)
);

一个表也可以包含多个外键约束。这个特性用于实现表之间的多对多关系。 比如你有关于产品和订单的表,但现在你想允许一个订单可以包含多种产品 (上面那个结构是不允许这么做的),你可以使用这样的结构:

CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
); CREATE TABLE orders (
order_id integer PRIMARY KEY,
shipping_address text,
...
); CREATE TABLE order_items (
product_no integer REFERENCES products,
order_id integer REFERENCES orders,
quantity integer,
PRIMARY KEY (product_no, order_id)
);

外键能通过 ALTER 语句添加或删除

2. 级联操作 ON DELETEON UPDATE

上面说过:外键约束声明一个字段(或者一组字段)的数值必须匹配另外一个表中出现的数值。

但是以 1. 中最后一个 sql 为例,如果一个订单(order)在创建之后,该订单包含的某个产品(product)被删除了,会发生什么?

这个例子中,订单包含的产品通过外键被记录在 order_items 表中。现在如果你要删除 product 中某个被 order_items 引用了的行,默认情况为 NO ACTION,就是直接报错。

这个行为也可以手动指定:

CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
); CREATE TABLE orders (
order_id integer PRIMARY KEY,
shipping_address text,
...
); CREATE TABLE order_items (
product_no integer REFERENCES products ON DELETE RESTRICT, -- 限制,也就是禁止删除被它引用的行
order_id integer REFERENCES orders ON DELETE CASCADE, -- 级联,在删除被它引用的行的时候,这一行本身也会被自动删除掉
quantity integer,
PRIMARY KEY (product_no, order_id)
);

除了 RESTRICTCASCADE 外,在外键上的动作还有两个选项:SET NULLSET DEFAULT,顾名思义,就是在被引用的行删除后将外键设置为 NULL 或默认值。

ON UPDATEON DELETE 的动作是一样的,只是 CASCADE 表示同步更新。

3. CHECK 约束

CREATE TABLE products (
product_no integer,
name text,
price numeric CHECK (price > 0)
);

你还可以给这个约束取一个独立的名字。这样就可以令错误消息更清晰, 并且在你需要修改它的时候引用这个名字。语法是:

CREATE TABLE products (
product_no integer,
name text,
price numeric CONSTRAINT positive_price CHECK (price > 0)
);

稍微复杂一点的例子:

CREATE TABLE products (
product_no integer,
name text,
price numeric CHECK (price > 0),
discounted_price numeric,
CHECK (discounted_price > 0 AND price > discounted_price)
);

同样的,可以为 CHECK 命名,令错误信息更清晰:

CREATE TABLE products (
product_no integer,
name text,
price numeric,
CHECK (price > 0),
discounted_price numeric,
CHECK (discounted_price > 0),
CONSTRAINT valid_discount CHECK (price > discounted_price)
);

要注意的是,当约束表达式计算结果为真或 NULL 的时候,检查约束会被认为是满足条件的。 因为大多数表达式在含有 NULL 操作数的时候结果都是 NULL ,所以这些约束不能阻止字段值为 NULL 。要排除掉 NULL,只能使用 NOT NULL 约束。(所以就说 NULL 是万恶之源hhh)

参考

SQL 基础笔记(三):约束的更多相关文章

  1. SQL 基础笔记(一)

    本笔记整理自<SQL 基础教程>.<MySQL 必知必会>和网上资料.个人笔记不保证正确. 一.基础 SQL,即结构化查询语言,是为访问与操作关系数据库中的数据而设计的语言. ...

  2. SQL 基础笔记(二):进阶查询

    本笔记整理自<SQL 基础教程>.<MySQL 必知必会>和网上资料.个人笔记不保证正确. 一.复杂查询 视图 将 SELECT 查询包装成一个虚拟表,该虚拟表就被称为视图.( ...

  3. MYSQL基础笔记(三)-表操作基础

    数据表的操作 表与字段是密不可分的. 新增数据表 Create table [if not exists] 表名( 字段名 数据类型, 字段名 数据类型, 字段n 数据类型 --最后一行不需要加逗号 ...

  4. SQL基础笔记

    Codecademy中Learn SQL, SQL: Table Transformaton和SQL: Analyzing Business Metrics三门课程的笔记,以及补充的附加笔记. Cod ...

  5. SQL学习笔记三(补充-3)之MySQL完整性约束

    阅读目录 一 介绍 二 not null与default 三 unique 四 primary key 五 auto_increment 六 foreign key 七 作业 一 介绍 约束条件与数据 ...

  6. SQL学习笔记三(补充-2)之MySQL数据类型

    阅读目录 一 介绍 二 数值类型 三 日期类型 四 字符串类型 五 枚举类型与集合类型 一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 ...

  7. 8、SQL基础整理(约束)

    约束 主键约束 防止在新增数据时出错,有约束性,起唯一标志的作用,在新增条目的时候防止不慎添加重复内容(不允许有null值) 1.  右键—设计—设置主键 2.在创建表格时设置 code int pr ...

  8. sql基础笔记备忘

    MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 数值类型:tinyint smallint medium ...

  9. SQL基础(三):SQL命令

    下面2个表用于实例演示: 1.SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列.列 ...

随机推荐

  1. EF6.0 对于数据库优 模式 新加功能

    EF6.0相对于5.0新加了很多功能.先看看两个模式的一些特点. 数据库优先(设计者)和代码优先两者的特点: 连接弹性 异步查询和保存 基于代码的配置 数据库命令记录 数据库命令截取 依赖决议 DbS ...

  2. Unity3d-制作粒子光环特效

    http://blog.csdn.net/ozhangseno/article/details/70799611

  3. 小白袍 -- Chapter 1 Java中的Encode与Decode

    前几天做一个邮件发送功能,一些常用信息配置在properties文件中,通过prop.getProperty(key)来获取配置的信息,结果配置文件中是用中文写的,邮件发送成功后,邮箱中的激活链接是乱 ...

  4. 为什么IP检验和发现错误直接丢弃而不是要求源站重发

    纠错控制由上层(传输层)执行IP首部中的源站地址也可能出错,请错误的源地址重传数据报是 没有意义的

  5. SmallMQ实现发布

    最近一直学习,主要处理java的分布式,MQ,RPC,通信,数据库,缓存等方向. 一般现在的MQ都是企业级的,庞大,功能齐全.最主要是代码量大,对于我们这些小程序员而言,太大,修改困难,修复更加困难, ...

  6. CommonJs模块规范

    1.什么是模块化 文件作用域 通信规则 加载 require 导出 exports 2.CommonJs模块规范 在Node中的Javascript还有一个很重要的概念:模块概念 模块作用域 使用re ...

  7. kali linux 中文出现乱码问题的解决

    确定locales已经安装,用”apt-get install locales”命令:之后可用”locale -a”查看当前系统支持的字符集. 1. 在命令行输入”dpkg-reconfigure l ...

  8. 关于Navicat连接MySQL 报 Authentication plugin 'caching_sha2_password' cannot be loaded

    报错原因: 报这个错是因为MySQL8使用了 caching_sha2_password 加密方式而之前MySQL使用的是 mysql_native_password 加密方式,而你的Navicat不 ...

  9. rabbitMq install for windows

    1.下载,erlang 安装rabbitmq需要erlang,下载erlang:http://www.erlang.org/downloads 2.下载rabbitMq rabbitMQ安装,查看安装 ...

  10. vue入门笔记

    Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还便于与 ...