本节知识点
知识点一: 子查询
知识点二: 连接查询
知识点三: MySQL中除了类型约束外的其他约束
创建数据库、数据表(学生、科目、成绩)
创建数据表代码如下:
CREATE TABLE students (
number CHAR(9),
name VARCHAR(20),
age INT,
birth DATE
);
INSERT INTO students VALUES ('201804001', '刘一', 16, '2002-01-01');
INSERT INTO students VALUES ('201804002', '陈二', 17, '2001-01-02');
INSERT INTO students VALUES ('201804003', '张三', 18, '2000-01-03');
INSERT INTO students VALUES ('201804004', '李四', 19, '2001-01-04');
INSERT INTO students VALUES ('201804005', '王五', 20, '2000-01-05');
INSERT INTO students VALUES ('201804006', '赵六', 21, '1999-01-06');
INSERT INTO students VALUES ('201804007', '孙七', 22, '1999-01-07');
INSERT INTO students VALUES ('201804008', '周八', 23, '1999-01-08');
INSERT INTO students VALUES ('201804009', '吴九', 24, '1999-01-09');
INSERT INTO students VALUES ('201804010', '郑十', 25, '1999-01-10');
select * from students;
+-----------+--------+------+------------+
| number | name | age | birth |
+-----------+--------+------+------------+
| 201804001 | 刘一 | 16 | 2002-01-01 |
| 201804001 | 陈二 | 17 | 2001-01-02 |
| 201804001 | 张三 | 18 | 2000-01-03 |
| 201804002 | 李四 | 19 | 2001-01-04 |
| 201804001 | 王五 | 20 | 2000-01-05 |
| 201804001 | 赵六 | 21 | 1999-01-06 |
| 201804001 | 孙七 | 22 | 1999-01-07 |
| 201804001 | 周八 | 23 | 1999-01-08 |
| 201804001 | 吴九 | 24 | 1999-01-09 |
| 201804001 | 郑十 | 25 | 1999-01-10 |
+-----------+--------+------+------------+
10 rows in set
CREATE TABLE subjects (
number CHAR(4),
title VARCHAR(30),
duration INT # 课时时长(单位:小时)
);
INSERT INTO subjects VALUES ('0001', 'Python基础', 32);
INSERT INTO subjects VALUES ('0002', 'Python进阶', 16);
INSERT INTO subjects VALUES ('0003', 'Web前端', 16);
INSERT INTO subjects VALUES ('0004', 'Python框架', 32);
INSERT INTO subjects VALUES ('0005', 'Python项目', 32);
select * from subjects;
输出结果:
+--------+--------------+----------+
| number | title | duration |
+--------+--------------+----------+
| 0001 | Python基础 | 32 |
| 0002 | Python进阶 | 16 |
| 0001 | Web前端 | 16 |
| 0001 | Python框架 | 32 |
| 0001 | Python项目 | 32 |
+--------+--------------+----------+
5 rows in set
CREATE TABLE grades (
student_number CHAR(9),
subject_number CHAR(4),
grade INT
);
INSERT INTO grades VALUES ('201804001', '0001', 90);
INSERT INTO grades VALUES ('201804002', '0001', 89);
INSERT INTO grades VALUES ('201804003', '0001', 88);
INSERT INTO grades VALUES ('201804004', '0001', 87);
INSERT INTO grades VALUES ('201804005', '0001', 86);
INSERT INTO grades VALUES ('201804006', '0001', 85);
INSERT INTO grades VALUES ('201804007', '0001', 84);
INSERT INTO grades VALUES ('201804008', '0001', 83);
INSERT INTO grades VALUES ('201804009', '0001', 82);
INSERT INTO grades VALUES ('201804010', '0001', 81);
INSERT INTO grades VALUES ('201804001', '0002', 80);
INSERT INTO grades VALUES ('201804002', '0002', 79);
INSERT INTO grades VALUES ('201804003', '0002', 78);
INSERT INTO grades VALUES ('201804004', '0002', 77);
INSERT INTO grades VALUES ('201804005', '0002', 76);
INSERT INTO grades VALUES ('201804006', '0002', 75);
INSERT INTO grades VALUES ('201804007', '0002', 74);
INSERT INTO grades VALUES ('201804008', '0002', 73);
INSERT INTO grades VALUES ('201804009', '0002', 72);
INSERT INTO grades VALUES ('201804010', '0002', 71);
select * from grades;
输出结果:
+----------------+----------------+-------+
| student_number | subject_number | grade |
+----------------+----------------+-------+
| 201804001 | 0001 | 90 |
| 201804002 | 0001 | 89 |
| 201804003 | 0001 | 88 |
| 201804004 | 0001 | 87 |
| 201804005 | 0001 | 86 |
| 201804006 | 0001 | 85 |
| 201804007 | 0001 | 84 |
| 201804008 | 0001 | 83 |
| 201804009 | 0001 | 82 |
| 201804010 | 0001 | 81 |
| 201804001 | 0002 | 80 |
| 201804002 | 0002 | 79 |
| 201804003 | 0002 | 78 |
| 201804004 | 0002 | 77 |
| 201804005 | 0002 | 76 |
| 201804006 | 0002 | 75 |
| 201804007 | 0002 | 74 |
| 201804008 | 0002 | 73 |
| 201804009 | 0002 | 72 |
| 201804010 | 0002 | 71 |
+----------------+----------------+-------+
20 rows in set (0.04 sec)
问题一:如何找到“张三”的成绩 ?
问题二:能否将一个查询的结果留下来用于下一次查询 ?
找到张三的成绩???
找到张三的学号,再用这个学号去筛选成绩表就能找到 !
现在的问题是 ?
我们都知道,我们要查的是成绩表。可是:
在查询 students 表之前,我们并不知道张三的学号是多少 !
如果把查询结果当作条件呢 ?
?
=SELECT number FROM students WHERE name=‘张三’; 问题一:如何在展示成绩的同时展示出其他相关信息 ?
问题二:能否将多张表拼在一起 ?
问题三:怎样才能保证新表数据的有效性 ?
交叉连接又名笛卡尔连接它列出了所有情况,其中一定有你需要的组合
交叉链接实现:
# 测试连接
CREATE TABLE a (
va INT
);
INSERT INTO a VALUES (1),(2),(3);
SELECT * FROM a;
CREATE TABLE b (
vb CHAR(1)
);
INSERT INTO b VALUES ('a'),('b');
SELECT * FROM ( a JOIN b );
输出结果:
INSERT INTO a VALUES (1),(2),(3);
SELECT * FROM a;
+------+
| va |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set
INSERT INTO b VALUES ('a'),('b');
SELECT * FROM b;
+------+
| vb |
+------+
| a |
| b |
+------+
2 rows in set
SELECT * FROM ( a JOIN b );
+------+------+
| va | vb |
+------+------+
| 1 | a |
| 1 | b |
| 2 | a |
| 2 | b |
| 3 | a |
| 3 | b |
+------+------+
6 rows in set
查找张三成绩的链接查询方式:
SELECT subject_number, grade
FROM ( students JOIN grades ON students.number=grades.student_number )
WHERE name='张三';
+----------------+-------+
| subject_number | grade |
+----------------+-------+
| 0001 | 88 |
| 0002 | 78 |
+----------------+-------+
2 rows in set (0.00 sec)
SELECT name, title, grade
FROM ( students JOIN grades
ON students.number=grades.student_number
JOIN subjects
ON grades.subject_number=subjects.number);
+--------+--------------+-------+
| name | title | grade |
+--------+--------------+-------+
| 刘一 | Python基础 | 90 |
| 刘一 | Python进阶 | 80 |
| 陈二 | Python基础 | 89 |
| 陈二 | Python进阶 | 79 |
| 张三 | Python基础 | 88 |
| 张三 | Python进阶 | 78 |
| 李四 | Python基础 | 87 |
| 李四 | Python进阶 | 77 |
| 王五 | Python基础 | 86 |
| 王五 | Python进阶 | 76 |
| 赵六 | Python基础 | 85 |
| 赵六 | Python进阶 | 75 |
| 孙七 | Python基础 | 84 |
| 孙七 | Python进阶 | 74 |
| 周八 | Python基础 | 83 |
| 周八 | Python进阶 | 73 |
| 吴九 | Python基础 | 82 |
| 吴九 | Python进阶 | 72 |
| 郑十 | Python基础 | 81 |
| 郑十 | Python进阶 | 71 |
+--------+--------------+-------+
20 rows in set (0.01 sec)
问题一: 如果插入一条记录的时候,某列没有插入值,会是什么 ?
问题二: 能否确保某列的值绝对不为空 ?
问题三: 能否确保某列的值不重复 ?
问题四: 能否确保某列的值必须参照另一列 ?
在没有设置的情况下,默认值为 NULL指定默认值的关键字是:
这样就可以在没有给定该列值的情况下,使用默认值
代码实现:
# 默认约束
CREATE TABLE t_default (
default_value INT
);
INSERT INTO t_default VALUES ();
SELECT * FROM t_default;
/*
+---------------+
| default_value |
+---------------+
| NULL |
+---------------+
1 row in set
*/
DROP TABLE t_default; # 删除这张表
CREATE TABLE t_default (
default_value INT DEFAULT 10
);
INSERT INTO t_default VALUES ();
SELECT * FROM t_default;
/*
+---------------+
| default_value |
+---------------+
| 10 |
+---------------+
1 row in set
*/
要限制一个列的值不能为空的关键字是:
这样,该列值就不能为NULL了。因此,如果不指定其他默认值,就必须在插入的时候给其赋值
代码实现:
# 非空约束
CREATE TABLE t_notnull (
notnull_value INT NOT NULL
);
INSERT INTO t_notnull VALUES ();
/*
ERROR 1364 (HY000): Field 'notnull_value' doesn't have a default value
*/
INSERT INTO t_notnull VALUES (1);
SELECT * FROM t_notnull;
/*
+---------------+
| notnull_value |
+---------------+
| 1 |
+---------------+
1 row in set
*/
如果希望某列的值不能重复,可是使用关键字:
这样,用UNIQUE KEY修饰的unique_value这一列的值就不能重复了
代码实现:
CREATE TABLE t_unique (
unique_value INT
);
INSERT INTO t_unique VALUE (1);
INSERT INTO t_unique VALUE (1);
SELECT * FROM t_unique;
/*
+--------------+
| unique_value |
+--------------+
| 1 |
| 1 |
+--------------+
2 rows in set
*/
DROP TABLE t_unique;
CREATE TABLE t_unique (
unique_value INT,
other_value INT,
UNIQUE KEY (unique_value)
);
INSERT INTO t_unique VALUE (1, 2);
INSERT INTO t_unique VALUE (2, 2);
SELECT * FROM t_unique;
/*
+--------------+-------------+
| unique_value | other_value |
+--------------+-------------+
| 1 | 2 |
| 2 | 2 |
+--------------+-------------+
2 rows in set
*/
INSERT INTO t_unique VALUE (1, 3);
/*
ERROR 1062 (23000): Duplicate entry '1' for key 'unique_value'
*/
通常,每张表都需要一个主键来体现唯一性:
主键 = 非空 + 唯一
代码实现:
# 主键约束
CREATE TABLE t_primarykey (
primarykey_value INT,
PRIMARY KEY (primarykey_value)
);
SHOW CREATE TABLE t_primarykey\G
/*
Table: t_primarykey
Create Table: CREATE TABLE `t_primarykey` (
`primarykey_value` int(11) NOT NULL,
PRIMARY KEY (`primarykey_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set
*/
INSERT INTO t_primarykey VALUES (1);
SELECT * FROM t_primarykey;
/*
+------------------+
| primarykey_value |
+------------------+
| 1 |
+------------------+
1 row in set
*/
INSERT INTO t_primarykey VALUES (1);
/*
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
*/
如果希望某整数列的值,默认+1填充:
注:AUTO_INCREMENT 要求用在主键上
代码实现:
# 自增长
CREATE TABLE t_auto (
auto_value INT AUTO_INCREMENT,
PRIMARY KEY (auto_value)
);
INSERT INTO t_auto VALUES ();
INSERT INTO t_auto VALUES ();
INSERT INTO t_auto VALUES ();
/*
+------------+
| auto_value |
+------------+
| 1 |
| 2 |
| 3 |
+------------+
3 rows in set
*/
我有的你一定有,你没有的,我绝对没有:
也就是说,创建c.d表时:在向 d 表插入值的时候,如果 d_col 的值不在 c表的 c_col 列中,则插入失败。
代码实现:
# 外键
CREATE TABLE c (
c_col INT,
PRIMARY KEY (c_col)
);
CREATE TABLE d (
d_col INT,
FOREIGN KEY (d_col) REFERENCES c(c_col)
);
INSERT INTO c VALUES (1), (2);
INSERT INTO d VALUES (1);
INSERT INTO d VALUES (3);
/*
ERROR 1452 (23000): Cannot add or update a child row:
a foreign key constraint fails (`python3`.`d`, CONSTRAINT `d_ibfk_1` FOREIGN KEY (`d_col`) REFERENCES `c` (`c_col`))
*/
INSERT INTO d VALUES (2);
INSERT INTO d VALUES (2);
SELECT * FROM d;
/*
+-------+
| d_col |
+-------+
| 1 |
| 2 |
| 2 |
+-------+
3 rows in set
*/
CREATE TABLE students (
id INT AUTO_INCREMENT ,
number CHAR(9) NOT NULL ,
name VARCHAR(20) NOT NULL ,
age INT DEFAULT 0 ,
birth DATE ,
UNIQUE KEY (number),
PRIMARY KEY (id)
);
INSERT INTO students VALUES (1,'201804001', '刘一', 16, '2002-01-01');
INSERT INTO students VALUES (2,'201804002', '陈二', 17, '2001-01-02');
INSERT INTO students VALUES (3,'201804003', '张三', 18, '2000-01-03');
INSERT INTO students VALUES (4,'201804004', '李四', 19, '2001-01-04');
INSERT INTO students VALUES (5,'201804005', '王五', 20, '2000-01-05');
INSERT INTO students VALUES (6,'201804006', '赵六', 21, '1999-01-06');
INSERT INTO students VALUES (7,'201804007', '孙七', 22, '1999-01-07');
INSERT INTO students VALUES (8,'201804008', '周八', 23, '1999-01-08');
INSERT INTO students VALUES (9,'201804009', '吴九', 24, '1999-01-09');
INSERT INTO students VALUES (10,'201804010', '郑十', 25, '1999-01-10');
SELECT * FROM students;
CREATE TABLE subjects (
id INT AUTO_INCREMENT,
number CHAR(4) NOT NULL,
title VARCHAR(30) NOT NULL,
duration INT NOT NULL,
UNIQUE KEY (number),
PRIMARY KEY (id)
);
INSERT INTO subjects VALUES (1,'0001', 'Python基础', 32);
INSERT INTO subjects VALUES (2,'0002', 'Python进阶', 16);
INSERT INTO subjects VALUES (3,'0003', 'Web前端', 16);
INSERT INTO subjects VALUES (4,'0004', 'Python框架', 32);
INSERT INTO subjects VALUES (5,'0005', 'Python项目', 32);
SELECT * FROM subjects;
CREATE TABLE grades (
id INT AUTO_INCREMENT,
student_number CHAR(9) NOT NULL,
subject_number CHAR(4) NOT NULL,
grade INT NOT NULL,
FOREIGN KEY (student_number) REFERENCES students(number),
FOREIGN KEY (subject_number) REFERENCES subjects(number),
UNIQUE KEY (student_number,subject_number ),
PRIMARY KEY (id)
);
INSERT INTO grades VALUES (1,'201804001', '0001', 90);
INSERT INTO grades VALUES (2,'201804002', '0001', 89);
INSERT INTO grades VALUES (3,'201804003', '0001', 88);
INSERT INTO grades VALUES (4,'201804004', '0001', 87);
INSERT INTO grades VALUES (5,'201804005', '0001', 86);
INSERT INTO grades VALUES (6,'201804006', '0001', 85);
INSERT INTO grades VALUES (7,'201804007', '0001', 84);
INSERT INTO grades VALUES (8,'201804008', '0001', 83);
INSERT INTO grades VALUES (9,'201804009', '0001', 82);
INSERT INTO grades VALUES (10,'201804010', '0001', 81);
INSERT INTO grades VALUES (11,'201804001', '0002', 80);
INSERT INTO grades VALUES (12,'201804002', '0002', 79);
INSERT INTO grades VALUES (13,'201804003', '0002', 78);
INSERT INTO grades VALUES (14,'201804004', '0002', 77);
INSERT INTO grades VALUES (15,'201804005', '0002', 76);
INSERT INTO grades VALUES (16,'201804006', '0002', 75);
INSERT INTO grades VALUES (17,'201804007', '0002', 74);
INSERT INTO grades VALUES (18,'201804008', '0002', 73);
INSERT INTO grades VALUES (19,'201804009', '0002', 72);
INSERT INTO grades VALUES (20,'201804010', '0002', 71);
SELECT * FROM grades;
输出结果:
+----+-----------+--------+------+------------+
| id | number | name | age | birth |
+----+-----------+--------+------+------------+
| 1 | 201804001 | 刘一 | 16 | 2002-01-01 |
| 2 | 201804002 | 陈二 | 17 | 2001-01-02 |
| 3 | 201804003 | 张三 | 18 | 2000-01-03 |
| 4 | 201804004 | 李四 | 19 | 2001-01-04 |
| 5 | 201804005 | 王五 | 20 | 2000-01-05 |
| 6 | 201804006 | 赵六 | 21 | 1999-01-06 |
| 7 | 201804007 | 孙七 | 22 | 1999-01-07 |
| 8 | 201804008 | 周八 | 23 | 1999-01-08 |
| 9 | 201804009 | 吴九 | 24 | 1999-01-09 |
| 10 | 201804010 | 郑十 | 25 | 1999-01-10 |
+----+-----------+--------+------+------------+
10 rows in set (0.00 sec)
+----+--------+--------------+----------+
| id | number | title | duration |
+----+--------+--------------+----------+
| 1 | 0001 | Python基础 | 32 |
| 2 | 0002 | Python进阶 | 16 |
| 3 | 0003 | Web前端 | 16 |
| 4 | 0004 | Python框架 | 32 |
| 5 | 0005 | Python项目 | 32 |
+----+--------+--------------+----------+
5 rows in set (0.00 sec)
+----+----------------+----------------+-------+
| id | student_number | subject_number | grade |
+----+----------------+----------------+-------+
| 1 | 201804001 | 0001 | 90 |
| 2 | 201804002 | 0001 | 89 |
| 3 | 201804003 | 0001 | 88 |
| 4 | 201804004 | 0001 | 87 |
| 5 | 201804005 | 0001 | 86 |
| 6 | 201804006 | 0001 | 85 |
| 7 | 201804007 | 0001 | 84 |
| 8 | 201804008 | 0001 | 83 |
| 9 | 201804009 | 0001 | 82 |
| 10 | 201804010 | 0001 | 81 |
| 11 | 201804001 | 0002 | 80 |
| 12 | 201804002 | 0002 | 79 |
| 13 | 201804003 | 0002 | 78 |
| 14 | 201804004 | 0002 | 77 |
| 15 | 201804005 | 0002 | 76 |
| 16 | 201804006 | 0002 | 75 |
| 17 | 201804007 | 0002 | 74 |
| 18 | 201804008 | 0002 | 73 |
| 19 | 201804009 | 0002 | 72 |
| 20 | 201804010 | 0002 | 71 |
+----+----------------+----------------+-------+
20 rows in set (0.00 sec)