Python-mysql数据库基础补充

Python-mysql数据库基础补充

本节知识点

知识点一: 子查询

知识点二: 连接查询

知识点三: MySQL中除了类型约束外的其他约束

part one : 学前准备

创建数据库、数据表(学生、科目、成绩)

创建数据表代码如下:

(1)创建学生表:
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
(2)创建科目表:
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
(3)创建成绩表:
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)

part two : 子查询

子查询 问题引入

问题一:如何找到“张三”的成绩 ?

问题二:能否将一个查询的结果留下来用于下一次查询 ?

找到张三的成绩???

找到张三的学号,再用这个学号去筛选成绩表就能找到 !

现在的问题是 ?

  • 我们都知道,我们要查的是成绩表。可是:

    • SELECT grade FROM grades WHERE student_number = ?
  • 在查询 students 表之前,我们并不知道张三的学号是多少 !

如果把查询结果当作条件呢 ?

  • SELECT subjects, grade FROM grades WHERE student_number=?;
    -?=SELECT number FROM students WHERE name=‘张三’;
    • 将学生表的查询结果嵌套进成绩表中!
  • 得到:SELECT subject_number, grade FROM grades WHERE ( SELECT number FROM students WHERE name=‘张三’ );

part third :连接查询

连接查询 问题引入

问题一:如何在展示成绩的同时展示出其他相关信息 ?

问题二:能否将多张表拼在一起 ?

问题三:怎样才能保证新表数据的有效性 ?

交叉连接

交叉连接又名笛卡尔连接它列出了所有情况,其中一定有你需要的组合

交叉链接实现:

# 测试连接
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)

part four :其他约束

其他约束 问题引入

问题一: 如果插入一条记录的时候,某列没有插入值,会是什么 ?

问题二: 能否确保某列的值绝对不为空 ?

问题三: 能否确保某列的值不重复 ?

问题四: 能否确保某列的值必须参照另一列 ?

默认值:

在没有设置的情况下,默认值为 NULL指定默认值的关键字是:

  • CREATE TABLE t_default (
    • default_value INT DEFAULT 10);

这样就可以在没有给定该列值的情况下,使用默认值

代码实现:

# 默认约束
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
*/
非空:

要限制一个列的值不能为空的关键字是:

  • CREATE TABLE t_notnull (
    • notnull_value INT NOT NULL);

这样,该列值就不能为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
*/
唯一键:

如果希望某列的值不能重复,可是使用关键字:

  • CREATE TABLE t_unique (
    • unique_value INT,
    • other_value INT,
    • UNIQUE KEY (unique_value)
    • );

这样,用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)
    • );

主键 = 非空 + 唯一

代码实现:

# 主键约束
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填充:

  • CREATE TABLE t_auto (
    • auto_value INT AUTO_INCREMENT,
    • PRIMARY KEY (auto_value)
    • );

注: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
*/
外键:

我有的你一定有,你没有的,我绝对没有:

  • CREATE TABLE c (
    • c_col INT,
    • PRIMARY KEY (c_col)
    • );
  • CREATE TABLE d (
    • d_col INT,
    • FOREIGN KEY (d_col) REFERENCES c(c_col)
    • );

也就是说,创建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)

你可能感兴趣的:(python,数据库基础)