MySQL有两种常用的引擎类型:MyISAM和InnoDB。目前只有InnoDB引擎类型支持外键约束。InnoDB中外键约束定义的语法如下:

 

例如:

 

InnoDB也支持使用ALTER TABLE来删除外键:

 

 

CASCADE
在父表上update/delete记录时,同步update/delete掉子表的匹配记录

SET NULL
在父表上update/delete记录时,将子表上匹配记录的列设为null (要注意子表的外键列不能为not null)

NO ACTION
如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作

RESTRICT
同no action, 都是立即检查外键约束

SET NULL
父表有变更时,子表将外键列设置成一个默认的值 但Innodb不能识别

 

NULL、RESTRICT、NO ACTION
删除:从表记录不存在时,主表才可以删除。删除从表,主表不变
更新:从表记录不存在时,主表才可以更新。更新从表,主表不变
CASCADE
删除:删除主表时自动删除从表。删除从表,主表不变
更新:更新主表时自动更新从表。更新从表,主表不变
 
SET NULL
删除:删除主表时自动更新从表值为NULL。删除从表,主表不变
更新:更新主表时自动更新从表值为NULL。更新从表,主表不变

 

外键约束属性: RESTRICT | CASCADE | SET NULL | NO ACTION  外键的使用需要满足下列的条件:

1. 两张表必须都是InnoDB表,并且它们没有临时表。

2. 建立外键关系的对应列必须具有相似的InnoDB内部数据类型。

3. 建立外键关系的对应列必须建立了索引。

4. 假如显式的给出了CONSTRAINT symbol,那symbol在数据库中必须是唯一的。假如没有显式的给出,InnoDB会自动的创建。

如果子表试图创建一个在父表中不存在的外键值,InnoDB会拒绝任何INSERT或UPDATE操作。如果父表试图UPDATE或者DELETE任何子 表中存在或匹配的外键值,最终动作取决于外键约束定义中的ON UPDATE和ON DELETE选项。InnoDB支持5种不同的动作,如果没有指定ON DELETE或者ON UPDATE,默认的动作为RESTRICT:

1. CASCADE: 从父表中删除或更新对应的行,同时自动的删除或更新自表中匹配的行。ON DELETE CANSCADE和ON UPDATE CANSCADE都被InnoDB所支持。

2. SET NULL: 从父表中删除或更新对应的行,同时将子表中的外键列设为空。注意,这些在外键列没有被设为NOT NULL时才有效。ON DELETE SET NULL和ON UPDATE SET SET NULL都被InnoDB所支持。

3. NO ACTION: InnoDB拒绝删除或者更新父表。

4. RESTRICT: 拒绝删除或者更新父表。指定RESTRICT(或者NO ACTION)和忽略ON DELETE或者ON UPDATE选项的效果是一样的。

5. SET DEFAULT: InnoDB目前不支持。

外键约束使用最多的两种情况无外乎:

1)父表更新时子表也更新,父表删除时如果子表有匹配的项,删除失败;

2)父表更新时子表也更新,父表删除时子表匹配的项也删除。

前一种情况,在外键定义中,我们使用ON UPDATE CASCADE ON DELETE RESTRICT;后一种情况,可以使用ON UPDATE CASCADE ON DELETE CASCADE。

 

当执行外键检查之时,InnoDB对它照看着的子或父记录设置共享的行级锁。InnoDB立即检查外键约束,检查不对事务提交延迟。

要使得对有外键关系的表重新载入转储文件变得更容易,mysqldump自动在转储输出中包括一个语句设置FOREIGN_KEY_CHECKS为0。这避免在转储被重新装载之时,与不得不被以特别顺序重新装载的表相关的问题。也可以手动设置这个变量:

mysql> SET FOREIGN_KEY_CHECKS = 0;

mysql> SOURCE dump_file_name;

mysql> SET FOREIGN_KEY_CHECKS = 1;

如果转储文件包含对外键是不正确顺序的表,这就以任何顺序导入该表。这样也加快导入操作。设置FOREIGN_KEY_CHECKS为0,对于在LOAD DATA和ALTER TABLE操作中忽略外键限制也是非常有用的。

InnoDB不允许你删除一个被FOREIGN KEY表约束引用的表,除非你做设置SET FOREIGN_KEY_CHECKS=0。当你移除一个表的时候,在它的创建语句里定义的约束也被移除。

如果你重新创建一个被移除的表,它必须有一个遵从于也引用它的外键约束的定义。它必须有正确的列名和类型,并且如前所述,它必须对被引用的键有索引。如果这些不被满足,MySQL返回错误号1005 并在错误信息字符串中指向errno 150。

 

 

 

 

 

无限级分类(或菜单)的高性能实现思路
2016-07-25 • Mysql、技术 • 12 条评论
一般说到无限级分类、菜单之类的东西,大家 (我) 的数据表设计一般是这样的

id parent_id title 更多字段…
1 0 衣物
2 1 上衣
3 1 裤子
4 3 西裤
5 4 长西裤
6 4 短西裤
7 2 衬衫

其中,parent_id表示父分类的id。由此可知,衣物分类下有上衣和裤子两个二级分类;而裤子还有西裤这个三级分类……以此类推

这种设计比较常见 (就我所知),但缺点很明显。
例如需要显示下面这样的面包屑导航时:
衣物 > 裤子 > 西裤
就不得不进行多次循环

再例如,需要显示所有分类并表示层级时:

也不得不进行多次循环

那么,如何快速实现上述的常见功能呢?

实现
首先,示例表设计:

id title path level 更多字段…
1 衣物 0 0
2 上衣 0,1 1
3 裤子 0,1 1
4 西裤 0,1,3 2
5 长西裤 0,1,3,4 3
6 短西裤 0,1,3,4 3
7 衬衫 0,1,2 2

其中,path表示父级id列表。例如西裤的0,1,3就表示衣物 > 裤子
实现面包屑时只要取出path字段的值,然后用,分割,得到id列表
再用where id in (1,3)即可

需要显示所有分类并表示层级时,使用下面的SQL:

看到的结果是这样的:

id title path level paths
1 衣物 0 0 0,1
2 上衣 0,1 1 0,1,2
7 衬衫 0,1,2 2 0,1,2,7
3 裤子 0,1 1 0,1,3
4 西裤 0,1,3 2 0,1,3,4
5 长西裤 0,1,3,4 3 0,1,3,4,5
6 短西裤 0,1,3,4 3 0,1,3,4,6

那么,直接取出结果输出即可。level字段就是层级的意思
例如在PHP中,可以用str_repeat(‘–> ‘, $level)直接输出表示层级的前缀
并且连顺序都排好了,是不是很方便呢?

 

1. 增:

2.删数据:

3. 改:

4.查:

 

mysql数据的导入导出

 

导入数据:

 

导出数据:

 

mysql 默认选择数据库的格式

utf8_general_ci