《MySQL技术内幕:InnoDB存储引擎》本书从源代码的角度深度解析了InnoDB的体系结构、实现原理、工作机制,并给出了大量实践,本着将书读薄的思想,循序渐进的记录对本书学习的读书笔记。

  关系型数据库系统和文件系统的一个不同点是,关系数据库本身能保证存储数据的完整性,不需要应用程序的控制,而文件系统一般需要在程序端进行控制。当前几乎所有的关系型数据库都提供了约束(constraits)机制,该机制提供了一条强大而简易的途径来保证数据库中的数据完整性,一般来说,数据完整性有以下三种形式:

(1)实体完整性保证表中有一个主键,在InnoDB存储引擎中,用户可以通过定义Primary Key或Unique Key约束来保证实体的完整性,用户还可以编写一个触发器来保证数据完整性、

(2)域完整性保证数据每列的值满足特定的条件。在InnoDB存储引擎中,域完整性可以通过以下途径来保证:

  a. 选择适合的数据类型确保一个数据值满足条件

  b. 外键(Foreign Key)约束

  c. 编写触发器

  d. 还可以考虑用default约束作为强制域完整性的一个方面

(3)参照完整性保证两张表之间的关系,InnoDB存储引擎提供了以下几种约束:

  a. primary key

  b. unique key

  c. foreign key

  d. default

  e. not null

1. 约束的创建和查找

  约束的创建有以下两种方式:

  (1)表建立时就进行约束定义

  (2)利用alter table命令来进行创建约束

  以下几点需要关注和注意:

  a. 对Unique Key(唯一索引)的约束,用户除了在创建时约定,还可以通过Create Unique Index来创建

  b. 对于主键约束耳音,其默认约束名为PRIMARY,而对于Unique Key约束而言,默认约束名和列名一样,当然也可以人为的指定Unique Key的名字,Foreign Key约束似乎会有一个比较神秘的默认名称

1.1 例1:创建表u,设置一个primary key和unique key

mysql> Create table u(
-> id int,
-> id_card varchar(),
-> name varchar(),
-> primary key(id),
-> unique key(name)
-> )engine=InnoDB;
Query OK, rows affected (0.56 sec) mysql> select constraint_name,constraint_type
-> from
-> information_schema.table_constraints
-> where table_schema='test' and table_name='u';
+-----------------+-----------------+
| constraint_name | constraint_type |
+-----------------+-----------------+
| PRIMARY | PRIMARY KEY |
| name | UNIQUE |
+-----------------+-----------------+
rows in set (0.01 sec)

  可以看到,约束名如上面所说,主键的约束名为PRIMARY,唯一索引的默认约束名与列名相同。

1.2 例2:alter table创建约束

mysql> alter table u
-> add unique key uk_id(id_card);
Query OK, rows affected (0.19 sec)
Records: Duplicates: Warnings: mysql> select constraint_name,constraint_type
-> from
-> information_schema.table_constraints
-> where table_schema='test' and table_name='u';
+-----------------+-----------------+
| constraint_name | constraint_type |
+-----------------+-----------------+
| PRIMARY | PRIMARY KEY |
| name | UNIQUE |
| uk_id | UNIQUE |
+-----------------+-----------------+
rows in set (0.00 sec)

1.3 例3:Foreign key的约束

mysql> create table p(
-> id int,
-> u_id int,
-> primary key(id),
-> foreign key(u_id) references p(id)
-> )engine=InnoDB;
Query OK, rows affected (0.41 sec) mysql> select constraint_name,constraint_type
-> from
-> information_schema.table_constraints
-> where table_schema='test' and table_name='p';
+-----------------+-----------------+
| constraint_name | constraint_type |
+-----------------+-----------------+
| PRIMARY | PRIMARY KEY |
| p_ibfk_1 | FOREIGN KEY |
+-----------------+-----------------+
rows in set (0.00 sec)

  在上面的例子中,通过information_schema架构下的表table_constraints来查看当前MySql库下所有的约束信息。

2. 对错误数据的约束

  在某些默认设置下,MySql数据库允许非法或不正确的数据的插入或更新,又或者可以在数据库内部将其转化为一个合法的值,如向not null的字段插入一个null值,MySql数据库会将其更改为0再进行插入,因此数据库本身没有对数据的正确性进行约束。

2.1 例1

mysql> Create table a(
-> id int not null,
-> data date not null
-> )engine=InnoDB;
Query OK, rows affected (0.20 sec) mysql> insert into a select NULL, '2009-02-20';
Query OK, row affected, warning (0.05 sec)
Records: Duplicates: Warnings:
mysql> select * from a;
+----+------------+
| id | data |
+----+------------+
| | -- |
+----+------------+
row in set (0.00 sec)

  通过设置参数set sql_mode='strict_trans_tables';对MySql数据库的输入值进行了约束,而且针对不同的错误提示错误内容也不同。

2.1 例2:enum与set约束

mysql> Create table a(
-> id int,
-> sex enum('male','female')
-> )engine=InnoDB;
Query OK, rows affected (0.17 sec) mysql> insert into a select ,'male';
Query OK, row affected (0.06 sec)
Records: Duplicates: Warnings: mysql> insert into a select ,'hello';
ERROR (): Data truncated for column 'sex' at row

3. 触发器与约束

3.1 触发器的认识

  触发器的作用是在执行insert,delete和update命令之前或之后自动调用sql命令或存储过程

3.1.1  触发器的创建

Create
[definer = { user | current_user}]
trigge trigger_name BEFORE|AFTER INSERT|UPDATE|DELETE
on tble_name FOR EACH ROW trigger_stmt

(1)最多可以为一个表建立6个触发器,即分别为insert,update,delete的before和after各定义一个

(2)只有表才支持触发器,视图不支持(临时表也不支持)

(3)如果before触发器失败,则MySQl将不执行请求的操作,此外如果before触发器或语句本身失败,MySql将不执行after触发器(如果有的话)

3.1.2  触发器的删除

  DROP TRIGGER trigger_name;

注:触发器不能更新或覆盖,为了修改一个触发器,必须先删除它,然后再重新创建

3.2 触发器约束

  假设有张用户消费表,每次用户购买一样物品后其金额都是减的,若这时有不坏好意的用户做了一个类似减去一个负值的操作,这样用户的钱没有减少反而不断增加

mysql> Create table usercash(
-> userid int not null,
-> cash int unsigned not null
-> ,
-> Primary key(userid))
-> engine=InnoDB;
Query OK, rows affected (0.16 sec) mysql> insert into usercash select ,;
Query OK, row affected (0.03 sec)
Records: Duplicates: Warnings: mysql> update usercash set cash=cash-(-) where userid = ;
Query OK, row affected (0.05 sec)
Rows matched: Changed: Warnings: mysql> select * from usercash;
+--------+------+
| userid | cash |
+--------+------+
| | |
+--------+------+
row in set (0.00 sec)

  上面运行的SQL语句对数据库来说没有任何的问题,都可以正常运行,不会报错。但从业务逻辑上来说,这是绝对错误的。下面采用触发器来约束这个逻辑行为:

mysql> Create table usercash_error_log(
-> userid int not null,
-> old_cash int unsigned not null,
-> new_cash int unsigned not null,
-> user varchar(),
-> time datetime,
-> primary key(userid)
-> )engine=InnoDB;
Query OK, rows affected (0.23 sec) mysql> delimiter //
mysql> Create trigger tgr_usercash_update before update on usercash
-> for each row
-> begin
-> if new.cash -old.cash> then
-> insert into usercash_error_log select old.userid, old.cash,new.cash,US
),NOW();
-> set new.cash=old.cash;
-> end if;
-> end//
Query OK, rows affected (0.05 sec) mysql> delimiter ;
mysql> delete from usercash;
Query OK, row affected (0.05 sec) mysql> insert into usercash select ,;
Query OK, row affected (0.05 sec)
Records: Duplicates: Warnings: mysql> update usercash set cash=cash-(-) where userid=;
Query OK, rows affected (0.11 sec)
Rows matched: Changed: Warnings: mysql> select * from usercash;
+--------+------+
| userid | cash |
+--------+------+
| | |
+--------+------+
row in set (0.00 sec) mysql> select * from usercash_error_log;
+--------+----------+----------+----------------+---------------------+
| userid | old_cash | new_cash | user | time |
+--------+----------+----------+----------------+---------------------+
| | | | root@localhost | -- :: |
+--------+----------+----------+----------------+---------------------+
row in set (0.00 sec)

  可以看出这次对于异常的数据更新通过触发器将其保存到了usercash_error_log。此外该触发器还记录了操作该SQL语句的用户和时间。 

4. 外键约束

外键用来保证参照完整性,MySQL数据库的MyIsAM存储引擎本身并不支持外键,对于外键的定义只是起到一个注释的作用,而InonoDB存储引擎则完整支持外键约束。

一般来说,称被引用的表为父表,引用的表称为子表,外键定义时的on delete和on update表示在对父表进行delete和updata操作时,对子表所做的操作。可定义的子表操作有:

(1)CASCADE

   表示当父表发生delete和update操作时,对相应的子表中的数据页进行delete和update操作

(2)SET FULL

  表示当父表发生delete和update操作时,相应的子表中的数据被更新为NULL值,但是子表中对应的列必须允许为NULL值

(3)NO ACTION

  表示父表发生delete或update操作时,抛出错误,不允许这类操作发生

(4)RESTRICT

  表示父表发生delete或update操作时,抛出错误,不允许这类操作发生,如果定义外键时没有指定on delete或on update,RESTRICT就是默认的外键设置

MySql数据库约束的更多相关文章

  1. MYSQL数据库约束类型

    07.14自我总结 MYSQL数据库约束类型 一.主键约束(primary key) 主键约束要求主键列的数据唯一,并且不能为空.主键分为两种类型:单字段主键和多字段联合主键. 1.单字段主键 写法 ...

  2. linux之-mysql数据库约束3

    在MySQL中,通常有这几种约束: DROP DATABASE mysql_shiyan;删除数据库 主键 (PRIMARY KEY)是用于约束表中的一行,作为这一行的唯一标识符,在一张表中通过主键就 ...

  3. MYSQL数据库-约束

    约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性.唯一性. MYSQL中,常用的几种约束: 约束类型: 主键 默认值 唯一 外键 非空 关键字: PRIMARY KEY DEF ...

  4. MySQL数据库有外键约束时使用truncate命令的办法

    MySQL数据库操作中,Delete与Truncate两个命令都可以删除一个数据表中的全部数据,使用办法分别是: DELETE FROM t_question TRUNCATE TABLE t_que ...

  5. Mysql 数据库设置三大范式 数据库五大约束 数据库基础配置

    数据库设置三大范式 1.第一范式(确保每列保持原子性) 第一范式是最基本的范式.如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库满足第一范式. 第一范式的合理遵循需要根据系统给的实际需求 ...

  6. MySQL数据库--外键约束及外键使用

    什么是主键.外键关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键. 比如: 学生表(学号,姓名,性别,班级) 其中每个学生的学号是唯 ...

  7. MySql数据库数据类型及约束介绍

    1,MySql中数据类型介绍 整型及浮点型 数据类型 存储范围 字节 TINYINT 有符号值:-2^到2^7-1 无符号值:0到2^8-1 2 SMALLINT 有符号值:-2^15到2^15-1 ...

  8. MySQL进阶:约束,多表设计,多表查询,视图,数据库备份与还原

    MySQL进阶 知识点梳理 一.约束 1. 外键约束 为什么要有外键约束 例如:一个user表,一个orderlist 如果现在想要直接删除id为1的张三,但是orderlist里还有用户id为1的订 ...

  9. mysql 数据库引擎

    一.数据库引擎 数据库引擎是用于存储.处理和保护数据的核心服务.利用数据库引擎可控制访问权限并快速处理事务,从而满足企业内大多数需要处理大量数据的应用程序的要求. 使用数据库引擎创建用于联机事务处理或 ...

随机推荐

  1. jelly

    http://pwnny.cn/original/2016/06/26/MakeBlog.html#NativeBuild01 Jekyll和Github搭建个人静态博客

  2. jdbc驱动jar导入eclipse

    在使用JDBC编程时需要连接数据库,导入JAR包是必须的,导入其它的jar包方法同样如此,导入的方法是 打开eclipse 1.右击要导入jar包的项目,点properties 2.左边选择java ...

  3. Linux系统资源查询命令(cpu、io、mem)

    cpu/mem: 1. 指定pid top -p pid1,pid2,... 2. top排序 先top,然后  输入大写P,则结果按CPU占用降序排序.输入大写M,结果按内存占用降序排序. io: ...

  4. RHEL 5 安装gcc

    rpm -ivh kernel-headers... rpm -ivh glibc-headers... rpm -ivh glibc-devel... rpm -ivh libgomp.. rpm ...

  5. React routerV4 笔记

    React routerV4 笔记     一.基础路由示例 import React from 'react' import { BrowserRouter as Router, Route, Li ...

  6. oracle长连接超时设置

    方法一.在sqlnet.ora中设置参数 如需要设置客户端空闲10分钟即被中断,则在sqlnet.ora的末尾添加SQLNET.EXPIRE_TIME=10注:sqlnet.ora文件的路径在$ORA ...

  7. 主攻ASP.NET MVC4.0之重生:Jquery Mobile 面板

    左滑动面板效果: 右滑动面板效果: @{ ViewBag.Title = "JQuery Mobile Web Page"; } <!DOCTYPE html> < ...

  8. 基于canvas与原生JS的H5动画引擎

    前一段时间项目组里有一些H5动画的需求,由于没有专业的前端人员,便交由我这个做后台的研究相关的H5动画技术. 通过初步调研,H5动画的实现大概有以下几种方式: 1.基于css实现 这种方式比较简单易学 ...

  9. json数据与Gson工具类的使用

    JS中使用JSON JSON对象 --> JSON字符串:JSON.stringify(对象) JSON字符串 --> JSON对象:JSON.parse(JSON字符串) <scr ...

  10. Phoenix性能优化

    目录: 1.建表优化 2.二级索引 3.并行处理 1.建表优化 Salting 翻译成中文是加盐的意思,本质是在hbase的rowkey的byte数组的第一个字节位置设定一个系统生成的byte值, 这 ...