《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. 前端基础之JavaScript_(5)_DOM对象总结

    DOM 定义了访问和操作HTML文档的标准方法 访问(查找标签) //---- 直接查找 document.getElementById(“idname”) document.getElementsB ...

  2. selenium模块控制浏览器

    利用selenium模块控制浏览器 导入selenium模块:from selenium import webdriver browserFirefox = webdriver.Firefox()#打 ...

  3. 【转】Linux下查看进程打开的文件句柄数

    ---查看系统默认的最大文件句柄数,系统默认是1024 # ulimit -n 1024 ----查看当前进程打开了多少句柄数 # lsof -n|awk '{print $2}'|sort|uniq ...

  4. Oracle索引(2)索引的修改与维护

    修改索引   利用alter index语句可以完成的操作 重建或合并索引 回收索引未使用的空间或为索引非配新空间 修改索引是否可以并行操作及并行度 修改索引的存储参数以及物理属性 指定Logging ...

  5. 每天一个Linux命令(40)vmstat命令

          vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存.进程.CPU活动进行监控. 它能够对系统的整体情况进行统计,无法对某个进程 ...

  6. .ssh中的文件的分别意义

    当我们在用户的主目录使用如下命令: cd (进入个人主目录,默认为/home/hadoop) ssh-keygen -t rsa -P '' (注:最后是二个单引号) 表示在用户的主目录创建ssh登陆 ...

  7. BCM 交换机开发

    转:http://blog.chinaunix.net/uid-23782786-id-3839602.html 前言:        最近搞这玩样,真是折腾,网上的资料都是片段,而且很少.折腾了4. ...

  8. 快乐学习 Ionic Framework+PhoneGap 手册1-1{创建APP项目}

    快乐学习 Ionic Framework+PhoneGap 手册1-1 * 前提必须安装 Node.js,安装PhoneGap,搭建Android开发环境,建议使用真机调试 {1.1}= 创建APP项 ...

  9. Class文件结构(更新中)

    Class文件是一组以8位字节为单位的二进制流,当遇见需要占用8位字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储. 格式,采用伪结构,只有两种数据结构:无符号数和表. 无符 ...

  10. 设置 IntelliJ IDEA 主题和字体的方法

    1 前言 在博文「IntelliJ IDEA 之 HelloWorld 项目创建及相关配置文件介绍」中,我们已经用 IntelliJ IDEA 创建了第一个 Java 项目 HelloWorld,如下 ...