zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

MySQL 的3个小知识点,你知道吗?

2023-06-13 09:15:41 时间

MySQL 的3个小知识点,你知道吗?

最近看了几个MySQL的小知识点,积累了一下,分享出来,给大家尝尝鲜。

01

MySQL 外键约束关键字

如果你经常使用MySQL的外键约束,可能对外键约束的关键字并不陌生。

常见的外键约束关键字有:cascade、restrict、no action和set default和set null,其中,

cascade:表示级联,父表的动作会级联到主表中;

restrict:表示严格模式,它是MySQL特有的关键字,表示父表的上不能直接删除或者更新有外键关联的记录;

no action:表示严格模式,标准SQL关键字,在MySQL中,它和restrict的意思相同;

set default:父表上的记录删除后,关联的子表记录会设置成默认值;

set null:父表上的记录删除后,关联的子表记录会设置成null值。

从上面的描述不难发现,no action和restrict既然意思相同,为什么不统一成一种?

从字面意思来看,no action似乎代表主表数据删除之后,子表上不发生任何动作;而restrict看起来是严格禁止主表删除数据的,但是实际上,二者在MySQL中,意思是一样的。所以MySQL保留了restrict的关键字,更加直观、有效。

看一个例子吧:

1、首先创建一个parent父表,并插入数据

mysql> show create table parent\G
*************************** 1. row ***************************
       Table: parent
Create Table: CREATE TABLE `parent` (
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> select * from parent;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
+----+

2、创建一个child的子表,并插入数据

mysql> show create table child\G
*************************** 1. row ***************************
       Table: child
Create Table: CREATE TABLE `child` (
  `id` int(11) DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  KEY `par_ind` (`parent_id`),
  CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) 
  REFERENCES `parent` (`id`) ON DELETE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> select *from child;
+------+-----------+
| id   | parent_id |
+------+-----------+
|    1 |         1 |
|    2 |         2 |
|    3 |         3 |
+------+-----------+
3 rows in set (0.01 sec)

3、parent父表上删除id=1的记录。

mysql> delete from parent where id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: 
a foreign key constraint fails (`test`.`child`, 
CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) 
REFERENCES `parent` (`id`) ON DELETE NO ACTION)

以上例子,说明no action跟restrict的含义是一样的。

02

table语法,你知道吗?

在MySQL中,查询一个表的所有数据,通常使用"select * from table_name"语法来查询, 在MySQL 8.0中,可以使用更加简单的语法:table table_name来对表数据进行查看。

如下:

MySQL 8.0.30
mysql> table child;
+------+-----------+
| id   | parent_id |
+------+-----------+
|    2 |         2 |
|    3 |         3 |
+------+-----------+
2 rows in set (0.00 sec)


mysql> select * from child;
+------+-----------+
| id   | parent_id |
+------+-----------+
|    2 |         2 |
|    3 |         3 |
+------+-----------+
2 rows in set (0.00 sec)

table 语法还可以跟limit、order by等关键字。

table语法和select * from table的语法,有2个重要区别:

1、table语法仅支持所有的列都显示,不支持过滤列。

2、table语法不支持where条件。

可以使用help 'table'命令去查看帮助,更多细节,请大家自己探索。

03

explain语法也能卡主MySQL?

看如下的SQL:

mysql> explain select * from ( select sleep(10)) t;
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table      | partitions | type   | possible_keys | key  | key_len | ref  | rows | filtered | Extra          |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
|  1 | PRIMARY     | <derived2> | NULL       | system | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL           |
|  2 | DERIVED     | NULL       | NULL       | NULL   | NULL          | NULL | NULL    | NULL | NULL |     NULL | No tables used |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
2 rows in set, 1 warning (10.01 sec)

通常的概念中,explain语法是查看执行计划的,不应该卡主MySQL才对.

然而,在上述例子中,当explain中包含一个sleep的子查询的时候,explain会先执行子查询,然后再输出结果,因此有一定可能阻塞住MySQL。

# DBA #