zoukankan      html  css  js  c++  java
  • 外键

    表结构1:

    CREATE TABLE `t1` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(20) DEFAULT NULL,
      `createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8

    表结构2:

     CREATE TABLE `t2` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_id` int(11) DEFAULT NULL,
      `createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`),
      KEY `t_id_fk` (`t_id`),
      CONSTRAINT `t_id_fk` FOREIGN KEY (`t_id`) REFERENCES `t1` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8

     设置了主键和外键的字段,默认会创建该字段的索引

    show index from t2;

     执行结果

    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | t2    |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
    | t2    |          1 | t_id_fk  |            1 | t_id        | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

    为t1插入数据

    +----+------+---------------------+
    | id | name | createtime          |
    +----+------+---------------------+
    |  1 | a    | 2018-06-27 10:51:36 |
    |  2 | b    | 2018-06-27 10:51:36 |
    |  3 | c    | 2018-06-27 10:51:36 |
    |  4 | d    | 2018-06-27 10:51:36 |
    +----+------+---------------------+

    为t2插入数据,由于外键约束的存在,t2(t_id)列的数据必须都来自于t1(id)列

    insert into t2 (t_id) values (5);

     执行结果

    ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`pmx`.`t2`, CONSTRAINT `t_id_fk` FOREIGN KEY (`t_id`) REFERENCES `t1` (`id`))
    insert into t2 (t_id) values (3),(2),(4),(3),(1),(4);

     执行结果

    +----+------+---------------------+
    | id | t_id | createtime          |
    +----+------+---------------------+
    |  2 |    3 | 2018-06-27 10:55:29 |
    |  3 |    2 | 2018-06-27 10:55:29 |
    |  4 |    4 | 2018-06-27 10:55:29 |
    |  5 |    3 | 2018-06-27 10:55:29 |
    |  6 |    1 | 2018-06-27 10:55:29 |
    |  7 |    4 | 2018-06-27 10:55:29 |
    +----+------+---------------------+

    t2.t_id字段的数据必须来自于t1.id,不能出现t1.id中没有的数据。id号从2开始,因为第一次插入5时失败了,但是auto_increment仍然从1变为了2。

    t_id字段的更新受外键的约束,取值范围只能来自于t1的id字段值。

    t2的删除操作不受外键的约束

    update t2 set t_id = 3 where id = 7;
    delete from t2 where id = 4;

     执行结果

    +----+------+---------------------+
    | id | t_id | createtime          |
    +----+------+---------------------+
    |  2 |    3 | 2018-06-27 10:55:29 |
    |  3 |    2 | 2018-06-27 10:55:29 |
    |  5 |    3 | 2018-06-27 10:55:29 |
    |  6 |    1 | 2018-06-27 10:55:29 |
    |  7 |    3 | 2018-06-27 10:55:29 |
    +----+------+---------------------+

    对主表t1执行删除操作时,如果删除的主键值在子表t2中出现,那么就删除失败

    delete from t1 where id = 4;

    执行结果

    +----+------+---------------------+
    | id | name | createtime          |
    +----+------+---------------------+
    |  1 | a    | 2018-06-27 10:51:36 |
    |  2 | b    | 2018-06-27 10:51:36 |
    |  3 | c    | 2018-06-27 10:51:36 |
    +----+------+---------------------+

    删除成功

    delete from t1 where id = 3;

    执行结果

    ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`pmx`.`t2`, CONSTRAINT `t_id_fk` FOREIGN KEY (`t_id`) REFERENCES `t1` (`id`)) 

    删除失败

     

    来看更新操作

    insert into t1 (name) values ('d'); 

     执行结果

    +----+------+---------------------+
    | id | name | createtime          |
    +----+------+---------------------+
    |  1 | a    | 2018-06-27 10:51:36 |
    |  2 | b    | 2018-06-27 10:51:36 |
    |  3 | c    | 2018-06-27 10:51:36 |
    |  5 | d    | 2018-06-27 11:06:24 |
    +----+------+---------------------+

    受auto_increment的特性影响,id变成了5

    update t1 set id = 7 where id = 5;

    执行结果

    +----+------+---------------------+
    | id | name | createtime          |
    +----+------+---------------------+
    |  1 | a    | 2018-06-27 10:51:36 |
    |  2 | b    | 2018-06-27 10:51:36 |
    |  3 | c    | 2018-06-27 10:51:36 |
    |  7 | d    | 2018-06-27 11:06:24 |
    +----+------+---------------------+

     更新成功。5和7并未在t2中出现

    update t1 set id = 8 where id =1;

    执行结果

    ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`pmx`.`t2`, CONSTRAINT `t_id_fk` FOREIGN KEY (`t_id`) REFERENCES `t1` (`id`)

    更新失败

    所以更新操作和删除操作一样,如果操作的值在子表中出现,那么就会操作失败

    truncate table t2;

    成功清空

    truncate table t1;
    ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint (`pmx`.`t2`, CONSTRAINT `t_id_fk` FOREIGN KEY (`t_id`) REFERENCES `pmx`.`t1` (`id`))

    为了能清空t1,我们只能先删除t2的外键再清空t1

    alter table t2 drop foreign key t_id_fk;
    alter table t2 drop key t_id_fk;
    truncate table t1;
    Query OK, 0 rows affected (0.02 sec)

    外键定制三种约束模式

      restrict和no action:父表更新或者删除时,子表有匹配记录,则禁止父表的更新和删除。默认选项

      cascade:父表更新或者删除时,子表有匹配记录,则父表操作成功,同时更新或删除子表匹配项

      set null:父表更新或者删除时,子表有匹配记录,则父表操作成功,同时将子表的匹配项设置为null值(前提能设置为null) 

    alter table t2 add constraint c_fk foreign key t_id references t1(id) [on {delete | update} { restrict | no action | cascade | set null}];
  • 相关阅读:
    【LeetCode】145. Binary Tree Postorder Traversal (3 solutions)
    【LeetCode】151. Reverse Words in a String
    【LeetCode】152. Maximum Product Subarray
    【LeetCode】154. Find Minimum in Rotated Sorted Array II (3 solutions)
    如何使用 Chrome 浏览器调试动态加载的 Javascript 脚本
    如何对数据库中的表以及表中的字段进行重命名
    关于 sql server 数据库权限乱七八糟的一些东西
    对 sql server 数据库的备份进行加密
    使用vs的查找功能,简单大概的统计vs中的代码行数
    在 sql server 中,查询 数据库的大小 和 数据库中各表的大小
  • 原文地址:https://www.cnblogs.com/bibiafa/p/9233023.html
Copyright © 2011-2022 走看看