MySQL数据操作
外键约束
只有InooDB存储引擎支持外键
非法数据无法写入
默认父表中的记录无法更新和删除
创建外键
- 建表时指定外键:[CONSTRAINT 外键名称] FOREIGN KEY (字段名称) REFERENCES 主表(字段名称);
子表的外键字段和主表的主键字段类型要相似;如果是数值型要求一致,并且无符号也要一致;如果是字符型要求类型一致,长度可以不同
如果是外键字段没有创建索引,MySQL会自动帮我们创建索引
子表的外键关联必须是父表的主键
mysql> -- 建立部门表
mysql> CREATE TABLE depart(
-> id INT UNSIGNED AUTO_INCREMENT KEY,
-> name VARCHAR(10)
-> )ENGINE=INNODB AUTO_INCREMENT=1 CHARSET=UTF8;
Query OK, 0 rows affected, 1 warning (1.38 sec)
mysql> -- 插入部门数据
mysql> INSERT INTO depart(name) VALUES
-> ("市场部"),
-> ("开发部"),
-> ("测试部"),
-> ("运营部");
Query OK, 4 rows affected (0.13 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> -- 建立员工表
mysql> CREATE TABLE emp(
-> id INT UNSIGNED AUTO_INCREMENT KEY,
-> name VARCHAR(10),
-> age TINYINT,
-> sex ENUM('男','女'),
-> depID INT UNSIGNED,
-> CONSTRAINT departID FOREIGN KEY (depID) REFERENCES depart(id)
-> )ENGINE=INNODB AUTO_INCREMENT=1 CHARSET=UTF8;
Query OK, 0 rows affected, 1 warning (2.06 sec)
mysql> -- 插入员工数据
mysql> INSERT INTO emp (name,age,sex,depID) VALUES
-> ("崔佛",33,'男',1),
-> ("富兰克林",34,'男',2),
-> ("麦克",35,'男',3),
-> ("艾琳",22,'女',3),
-> ("杰克",21,'男',2),
-> ("琼斯",20,'男',4);
Query OK, 6 rows affected (0.23 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> -- 通过外键查询
mysql> SELECT * FROM emp;
+----+----------+------+------+-------+
| id | name | age | sex | depID |
+----+----------+------+------+-------+
| 7 | 崔佛 | 33 | 男 | 1 |
| 8 | 富兰克林 | 34 | 男 | 2 |
| 9 | 麦克 | 35 | 男 | 3 |
| 10 | 艾琳 | 22 | 女 | 3 |
| 11 | 杰克 | 21 | 男 | 2 |
| 12 | 琼斯 | 20 | 男 | 4 |
+----+----------+------+------+-------+
6 rows in set (0.00 sec)
- 动态删除外键:ALTER TABLE tbl_name DROP FOREIGNN KEY fk_name;
- 动态添加外键:ALTER TABLE tbl_name ADD FOREIGN KEY(外键字段) REFERENCES 主表(主键字段)
动态添加外键时表中的记录一定合法,没有脏值,否则添加不成功
外键约束的参照操作:
- CASCADE:从父表中删除或更新,子表也跟着删除或更新,级联的操作
- SET NULL:从父表删除或过呢更新记录并设置子表的外键列为NULL
- NO ACTION|RESTRICT 拒绝对父表 做更新或删除操作(默认)
特殊形式的查询——子查询
SELECT 字段名称 FROM tbl_name WHERE col_name=(SELECT col_name FROM tbl_name)
内层语句可查询的结果可以作为外层查询的条件
mysql> -- 建立部门表
mysql> CREATE TABLE depart(
-> id INT UNSIGNED AUTO_INCREMENT KEY,
-> name VARCHAR(10)
-> )ENGINE=INNODB AUTO_INCREMENT=1 CHARSET=UTF8;
Query OK, 0 rows affected, 1 warning (0.97 sec)
mysql> -- 插入部门数据
mysql> INSERT INTO depart(name) VALUES
-> ("市场部"),
-> ("开发部"),
-> ("测试部"),
-> ("运营部");
Query OK, 4 rows affected (0.30 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> -- 建立员工表
mysql> CREATE TABLE emp(
-> id INT UNSIGNED AUTO_INCREMENT KEY,
-> name VARCHAR(10),
-> age TINYINT,
-> sex ENUM('男','女'),
-> depID INT UNSIGNED
-> )ENGINE=INNODB AUTO_INCREMENT=1 CHARSET=UTF8;
Query OK, 0 rows affected, 1 warning (1.04 sec)
mysql> -- 插入员工数据
mysql> INSERT INTO emp (name,age,sex,depID) VALUES
-> ("崔佛",33,'男',1),
-> ("富兰克林",34,'男',2),
-> ("麦克",35,'男',3),
-> ("艾琳",22,'女',3),
-> ("杰克",21,'男',2),
-> ("琼斯",20,'男',5);
Query OK, 6 rows affected (0.25 sec)
Records: 6 Duplicates: 0 Warnings: 0
由IN引发的子查询
mysql> -- 由IN引发的子查询
mysql> SELECT * FROM emp WHERE depID IN (SELECT id FROM depart);
+----+----------+------+------+-------+
| id | name | age | sex | depID |
+----+----------+------+------+-------+
| 1 | 崔佛 | 33 | 男 | 1 |
| 2 | 富兰克林 | 34 | 男 | 2 |
| 3 | 麦克 | 35 | 男 | 3 |
| 4 | 艾琳 | 22 | 女 | 3 |
| 5 | 杰克 | 21 | 男 | 2 |
+----+----------+------+------+-------+
5 rows in set (0.00 sec)
由比较运算符引发的子查询
mysql> -- 由比较运算符引发的子查询
mysql> SELECT * FROM emp WHERE depID>=(SELECT id FROM depart WHERE name="开发部");
+----+----------+------+------+-------+
| id | name | age | sex | depID |
+----+----------+------+------+-------+
| 2 | 富兰克林 | 34 | 男 | 2 |
| 3 | 麦克 | 35 | 男 | 3 |
| 4 | 艾琳 | 22 | 女 | 3 |
| 5 | 杰克 | 21 | 男 | 2 |
| 6 | 琼斯 | 20 | 男 | 5 |
+----+----------+------+------+-------+
5 rows in set (0.00 sec)
由EXISTS引发的子查询
mysql> -- 由EXISTS引发的子查询(判断exits后的语句是否成立,成立则执行前语句,否则不执行)
mysql> SELECT * FROM emp WHERE EXISTS (SELECT * FROM depart WHERE id=6);
Empty set (0.00 sec)
mysql> SELECT * FROM emp WHERE EXISTS (SELECT * FROM depart WHERE id=2);
+----+----------+------+------+-------+
| id | name | age | sex | depID |
+----+----------+------+------+-------+
| 1 | 崔佛 | 33 | 男 | 1 |
| 2 | 富兰克林 | 34 | 男 | 2 |
| 3 | 麦克 | 35 | 男 | 3 |
| 4 | 艾琳 | 22 | 女 | 3 |
| 5 | 杰克 | 21 | 男 | 2 |
| 6 | 琼斯 | 20 | 男 | 5 |
+----+----------+------+------+-------+
6 rows in set (0.00 sec)
由ANY SOME ALL关键字引发的子查询
运算符 关键字 | ANY | SOME | ALL |
---|---|---|---|
>,>= | 最小值 | 最小值 | 最大值 |
<,<= | 最大值 | 最大值 | 最小值 |
= | 任意值 | 任意值 | |
<>,!= | 任意值 |
表示大于或小于或等于或不等于内层查询结果的最大值或最小值或任意值
通过子查询将一个表中的数据写入另一个表中
- INSERT … SELECT
- CREATE … SELECT
mysql> -- 建表1
mysql> CREATE TABLE test1(
-> id INT UNSIGNED AUTO_INCREMENT KEY,
-> name VARCHAR(10)
-> )ENGINE=INNODB AUTO_INCREMENT=1 CHARSET=UTF8;
Query OK, 0 rows affected, 1 warning (0.50 sec)
mysql> -- 插入记录
mysql> INSERT INTO test1(name) VALUES
-> ("张三"),
-> ("李四"),
-> ("王五"),
-> ("令狐冲");
Query OK, 4 rows affected (0.13 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> -- 利用表1数据建表2
mysql> CREATE TABLE test2(
-> id INT UNSIGNED AUTO_INCREMENT KEY,
-> name VARCHAR(10)
-> )SELECT * FROM test1 WHERE id <=3;
Query OK, 3 rows affected (1.38 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test2;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
+----+------+
3 rows in set (0.00 sec)
mysql> -- 查询表1记录插入2中
mysql> INSERT INTO test2 SELECT * FROM test1 WHERE id=4;
Query OK, 1 row affected (0.17 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test2;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
| 4 | 令狐冲 |
+----+--------+
4 rows in set (0.00 sec)
联合查询
- UNION:SELECT 字段名称,… FROM tbl_name1 UNION SELECT 字段名称,… FROM tbl_name2;
- UNION ALL:SELECT 字段名称,… FROM tbl_name1 UNION SELECT 字段名称… FROM tbl_name2;
mysql> -- 联合查询
mysql> SELECT * FROM test1 UNION SELECT * FROM test2;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
| 4 | 令狐冲 |
+----+--------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM test1 UNION ALL SELECT * FROM test2;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
| 4 | 令狐冲 |
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
| 4 | 令狐冲 |
+----+--------+
8 rows in set (0.00 sec)
UNION ALL是简单的合并,UNION会去掉重复的记录
使用UNION进行联合查询时,两个表查询的字段数需要一致,倘若不一致,直接使用select+待查字段+from+表名+where+外键条件判断
自身连接查询——无限级分类的实现形式
mysql> -- 建表
mysql> CREATE TABLE test(
-> id INT UNSIGNED AUTO_INCREMENT KEY,
-> name VARCHAR(10),
-> Xid INT UNSIGNED
-> )ENGINE=INNODB AUTO_INCREMENT=1 CHARSET=UTF8;
Query OK, 0 rows affected, 1 warning (2.11 sec)
mysql> -- 插入记录
mysql> INSERT INTO test(name,Xid) VALUES
-> ("张三",2),
-> ("李四",3),
-> ("王五",3);
Query OK, 3 rows affected (0.43 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> -- 自身连接查询
mysql> SELECT * FROM test AS one LEFT JOIN test AS two ON one.id=two.Xid;
+----+------+------+------+------+------+
| id | name | Xid | id | name | Xid |
+----+------+------+------+------+------+
| 1 | 张三 | 2 | NULL | NULL | NULL |
| 2 | 李四 | 3 | 1 | 张三 | 2 |
| 3 | 王五 | 3 | 2 | 李四 | 3 |
| 3 | 王五 | 3 | 3 | 王五 | 3 |
+----+------+------+------+------+------+
4 rows in set (0.00 sec)