mysql关系表_mysql表关系

mysql数据库

知识要点:

单表查询

子查询

联表查询

事务

在进行查询之前,我们要先建好关系表,并往数据表中插入些数据。为查询操作做好准备。

五张关系表的创建:

#创建并进入数据库:

mysql>CREATEDATABASE`info`;

QueryOK,1rowaffected (0.00sec)

mysql>USE`info`;

Databasechanged

#创建学院表:

mysql>CREATETABLE`department`(

->`id`INTPRIMARYKEYAUTO_INCREMENT,

->`name`VARCHAR(20)NOTNULL

-> );

QueryOK,0rows affected (0.69sec)

#创建学生表:

mysql>CREATETABLE`students`(

->`s_id`INTPRIMARYKEYAUTO_INCREMENT,

->`name`VARCHAR(20)NOTNULL,

->`d_id`INT,

->FOREIGNKEY(`d_id`)REFERENCES`department`(`id`)

-> );

QueryOK,0rows affected (0.65sec)

#创建学生的详细信息表:

mysql>CREATETABLE`stu_details`(

->`s_id`INTPRIMARYKEY,

->`age`INT,

->`gender`CHAR(1)

-> ,

->FOREIGNKEY(`s_id`)REFERENCES`students`(`s_id`)

-> );

QueryOK,0rows affected (0.55sec)

#创建课程表:

mysql>CREATETABLE`course`(

->`id`INTPRIMARYKEYAUTO_INCREMENT,

->`name`VARCHAR(20)NOTNULL

-> );

QueryOK,0rows affected (0.50sec)

#创建中间表:

mysql>CREATETABLE`select`(

->`s_id`INT,

->`c_id`INT,

->PRIMARYKEY(`s_id`,`c_id`),

->FOREIGNKEY(`s_id`)REFERENCES`students`(`s_id`),

->FOREIGNKEY(`c_id`)REFERENCES`course`(`id`)

-> );

QueryOK,0rows affected (0.84sec)

#查看当前存在的表:

mysql>SHOWTABLES;

+----------------+

| Tables_in_info |

+----------------+

| course         |

| department     |

|select|

| stu_details    |

| students       |

+----------------+

5rowsinset(0.00sec)

往数据表中添加数据

#往学院表中添加数据:

mysql>INSERTINTO`department`(`name`)

->VALUES('外国语'),

->       ('艺术'),

->       ('计算机'),

->       ('化工')

-> ;

QueryOK,4rows affected (0.11sec)

Records:4Duplicates:0Warnings:0

#往学生表中添加数据:

mysql>INSERTINTO`students`(`name`,`d_id`)

->VALUES('小明',1),

->       ('小红',3),

->       ('小花',3),

->       ('小新',4)

-> ;

QueryOK,4rows affected (0.09sec)

Records:4Duplicates:0Warnings:0

#往学生详细信息表中添加数据:

mysql>INSERTINTOstu_details

->VALUES(1,18,'m'),

->       (4,20,'m'),

->       (3,16,'f'),

->       (2,19,'f')

-> ;

QueryOK,4rows affected (0.11sec)

Records:4Duplicates:0Warnings:0

#往课程表中添加数据:

mysql>INSERTINTO`course`

-> (`name`)VALUES

-> ('心理学'),

-> ('佛学'),

-> ('近代史'),

-> ('音乐鉴赏')

-> ;

QueryOK,4rows affected (0.08sec)

Records:4Duplicates:0Warnings:0

#查看中间表的结构:

mysql>DESC`select`;

+-------+---------+------+-----+---------+-------+

|Field| Type    |Null|Key|Default| Extra |

+-------+---------+------+-----+---------+-------+

| s_id  |int(11) |NO| PRI |NULL|       |

| c_id  |int(11) |NO| PRI |NULL|       |

+-------+---------+------+-----+---------+-------+

2rowsinset(0.03sec)

#往中间表中添加数据

mysql>INSERTINTO`select`

->VALUES(1,2),

->       (1,4),

->       (2,1),

->       (2,4),

->       (4,1),

->       (4,2),

->       (4,4)

-> ;

QueryOK,7rows affected (0.06sec)

Records:7Duplicates:0Warnings:0

查询

查询所有记录

SELECT * FROM  tb_name;

查询选中列记录

SELECT col_name1,col_name2 FROM tb_name;

查询指定条件下的记录

SELECT col_name FROM  tb_name  WHERE 条件

查询后为列取别名

SELECT  col_name  AS  new_name  FROM  tab_name

#查询所有记录:

mysql>SELECT*FROM`students`;

+------+--------+------+

| s_id | name   | d_id |

+------+--------+------+

|1| 小明   |1|

|2| 小红   |3|

|3| 小花   |3|

|4| 小新   |4|

+------+--------+------+

4rowsinset(0.00sec)

#查询选中列记录

mysql>SELECTname,d_idFROMstudents;

+--------+------+

| name   | d_id |

+--------+------+

| 小明   |1|

| 小红   |3|

| 小花   |3|

| 小新   |4|

+--------+------+

4rowsinset(0.00sec)

#查询指定条件下的记录

mysql>SELECT*FROMstudentsWHERE`name`='小红';

+------+--------+------+

| s_id | name   | d_id |

+------+--------+------+

|2| 小红   |3|

+------+--------+------+

1rowinset(0.00sec)

#查询后为列取别名

mysql>SELECTnameAS`姓名`,d_idAS学院idFROMstudentsWHEREs_id>=2;

+--------+----------+

| 姓名   | 学院id   |

+--------+----------+

| 小红   |3|

| 小花   |3|

| 小新   |4|

+--------+----------+

3rowsinset(0.00sec)

排序ORDER BY

ASC升序(默认)  DESC降序

#查询学生的选修表(中间表)

mysql>SELECT*FROM`select`;

+------+------+

| s_id | c_id |

+------+------+

|2|1|

|4|1|

|1|2|

|4|2|

|1|4|

|2|4|

|4|4|

+------+------+

7rowsinset(0.00sec)

#按学生学号升序输出

mysql>SELECT*FROM`select`ORDERBY`s_id`;

+------+------+

| s_id | c_id |

+------+------+

|1|2|

|1|4|

|2|1|

|2|4|

|4|1|

|4|2|

|4|4|

+------+------+

7rowsinset(0.00sec)

#按课程id降序输出:

mysql>SELECT*FROM`select`ORDERBY`c_id`DESC;

+------+------+

| s_id | c_id |

+------+------+

|4|4|

|2|4|

|1|4|

|4|2|

|1|2|

|4|1|

|2|1|

+------+------+

7rowsinset(0.00sec)

限制显示数据的数量LIMIT

#按学生学号升序输出的前4条数据

mysql>SELECT*FROM`select`ORDERBY`s_id`LIMIT4;

+------+------+

| s_id | c_id |

+------+------+

|1|2|

|1|4|

|2|1|

|2|4|

+------+------+

4rowsinset(0.00sec)

#指定的返回的数据的位置和数量

mysql>SELECT*FROM`select`ORDERBY`s_id`LIMIT4,2;

+------+------+

| s_id | c_id |

+------+------+

|4|1|

|4|2|

+------+------+

2rowsinset(0.00sec)

分组查询GROUP BY

例:

对学生表中学院栏进行分组,并统计学院的学生人数:

mysql> SELECT d_id AS 学院id,count(d_id) AS 学生个数 FROM students GROUP BY `d_id`;

+----------+--------------+

| 学院id   | 学生个数     |

+----------+--------------+

|        1 |            1 |

|        3 |            2 |

|        4 |            1 |

+----------+--------------+

3 rows in set (0.00 sec)

HAVING分组条件

HAVING 后的字段必须是SELECT后出现过的

mysql> SELECT d_id AS 学院id,count(d_id) AS 学生个数 FROM students GROUP BY `d_id`HAVING  学生个数=1;

+----------+--------------+

| 学院id   | 学生个数     |

+----------+--------------+

|        1 |            1 |

|        4 |            1 |

+----------+--------------+

2 rows in set (0.01 sec)

查询中一些较为常见的函数

#求最大年龄

mysql>SELECTMAX(`age`)FROM`stu_details`;

+------------+

|MAX(`age`) |

+------------+

|20|

+------------+

1rowinset(0.03sec)

#求最小年龄

mysql>SELECTMIN(`age`)FROM`stu_details`;

+------------+

|MIN(`age`) |

+------------+

|16|

+------------+

1rowinset(0.00sec)

#求和

mysql>SELECTSUM(`age`)FROM`stu_details`;

+------------+

|SUM(`age`) |

+------------+

|73|

+------------+

1rowinset(0.05sec)

#求平均数

mysql>SELECTAVG(`age`)FROM`stu_details`;

+------------+

|AVG(`age`) |

+------------+

|18.2500|

+------------+

1rowinset(0.00sec)

子查询

出现在其他SQL语句内的SELECT字句。

1)嵌套在查询内部2)必须始终出现在圆括号内3)可以包含多个关键字或条件

#查找出大于平均年龄的数据

mysql>SELECT*FROM`stu_details`WHERE`age`>18.25;

+------+------+--------+

| s_id | age  | gender |

+------+------+--------+

|2|19| f      |

|4|20| m      |

+------+------+--------+

2rowsinset(0.00sec)

#将平均数的SQL语句作为子查询放入上一条语句中

mysql>SELECT*FROM`stu_details`WHERE`age`>(SELECTAVG(`age`)FROM`stu_details`);

+------+------+--------+

| s_id | age  | gender |

+------+------+--------+

|2|19| f      |

|4|20| m      |

+------+------+--------+

2rowsinset(0.10sec)

联表查询

内连接[INNER| CROSS] JOIN

无条件内连接:无条件内连接,又名交叉连接/笛卡尔连接第一张表种的每一向会和另一张表的每一项依次组合

有条件内连接在无条件的内连接基础上,加上一个ON子句当连接的时候,筛选出那些有实际意义的记录行来进行拼接

在写条件时注意两张表的列名是否一样,如果时一样的则要在前面加上表名,tb_name.colname这种形式存在

#无条件内连接:

mysql>SELECT*FROM`students`INNERJOIN`department`;

+------+--------+------+----+-----------+

| s_id | name   | d_id | id | name      |

+------+--------+------+----+-----------+

|1| 小明   |1|1| 外国语    |

|2| 小红   |3|1| 外国语    |

|3| 小花   |3|1| 外国语    |

|4| 小新   |4|1| 外国语    |

|1| 小明   |1|2| 艺术      |

|2| 小红   |3|2| 艺术      |

|3| 小花   |3|2| 艺术      |

|4| 小新   |4|2| 艺术      |

|1| 小明   |1|3| 计算机    |

|2| 小红   |3|3| 计算机    |

|3| 小花   |3|3| 计算机    |

|4| 小新   |4|3| 计算机    |

|1| 小明   |1|4| 化工      |

|2| 小红   |3|4| 化工      |

|3| 小花   |3|4| 化工      |

|4| 小新   |4|4| 化工      |

+------+--------+------+----+-----------+

16rowsinset(0.04sec)

#有条件内连接:

mysql>SELECT*FROM`students`INNERJOIN`department`

->ONd_id=id;

+------+--------+------+----+-----------+

| s_id | name   | d_id | id | name      |

+------+--------+------+----+-----------+

|1| 小明   |1|1| 外国语    |

|2| 小红   |3|3| 计算机    |

|3| 小花   |3|3| 计算机    |

|4| 小新   |4|4| 化工      |

+------+--------+------+----+-----------+

4rowsinset(0.03sec)

有条件的外连接:{ LEFT| RIGHT } [OUTER] JOIN

左外连接:两张表做连接的时候,在连接条件不匹配的时候留下左表中的数据,而右表中的数据以NULL填充

右外连接对两张表做连接的时候,在连接条件不匹配的时候留下右表中的数据,而左表中的数据以NULL填充

#往学生表中添加数据,只添加名字

mysql>INSERTINTOstudents(name)

->VALUES('xixi');

QueryOK,1rowaffected (0.11sec)

#查看所有学生表数据

mysql>SELECT*FROMstudentS;

+------+--------+------+

| s_id | name   | d_id |

+------+--------+------+

|1| 小明   |1|

|2| 小红   |3|

|3| 小花   |3|

|4| 小新   |4|

|5| xixi   |NULL|

+------+--------+------+

5rowsinset(0.00sec)

#使用内连接加条件只能看到有分配好学院的学生的信息;

mysql>SELECT*FROMstudentsINNERJOINdepartment

->ONd_id=id;

+------+--------+------+----+-----------+

| s_id | name   | d_id | id | name      |

+------+--------+------+----+-----------+

|1| 小明   |1|1| 外国语    |

|2| 小红   |3|3| 计算机    |

|3| 小花   |3|3| 计算机    |

|4| 小新   |4|4| 化工      |

+------+--------+------+----+-----------+

4rowsinset(0.02sec)

#使用左连接把学生的数据全取出来,该学生没有学院信息的用NULL填充

mysql>SELECT*FROMstudentsLEFTJOINdepartment

->ONd_id=id;

+------+--------+------+------+-----------+

| s_id | name   | d_id | id   | name      |

+------+--------+------+------+-----------+

|1| 小明   |1|1| 外国语    |

|2| 小红   |3|3| 计算机    |

|3| 小花   |3|3| 计算机    |

|4| 小新   |4|4| 化工      |

|5| xixi   |NULL|NULL|NULL|

+------+--------+------+------+-----------+

5rowsinset(0.00sec)

#使用右外连接把目前还没有学生的学院的数据也显示出来

mysql>SELECT*FROMstudentsRIGHTJOINdepartment

->ONd_id=id;

+------+--------+------+----+-----------+

| s_id | name   | d_id | id | name      |

+------+--------+------+----+-----------+

|1| 小明   |1|1| 外国语     |

|2| 小红   |3|3| 计算机     |

|3| 小花   |3|3| 计算机     |

|4| 小新   |4|4| 化工       |

|NULL|NULL|NULL|2| 艺术      |

+------+--------+------+----+-----------+

5rowsinset(0.00sec)

mysql>

查询SQL的优化

MySQL的执行顺序

1.FROM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1

2.ON: 对虚表VT1进行ON筛选,只有那些符合的行才会被记录在虚表VT2中。

3.JOIN: 如果指定了OUTERJOIN(比如leftjoin、rightjoin),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rugfrom子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。

4.WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4中。

5.GROUPBY: 根据groupby子句中的列,对VT4中的记录进行分组操作,产生VT5.

6.CUBE |ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.

7.HAVING: 对虚拟表VT6应用having过滤,只有符合的记录才会被 插入到虚拟表VT7中。

8.SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。

9.DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.

10.ORDERBY: 将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10.

11.LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

通过上面的执行顺序不难想到,要想SQL执行更快,就必须把筛选条件尽量的往前面放。如下:

SELECT

s.`name`,

e.`name`

FROM

`students`s

LEFTJOIN(

SELECT

se.`s_id`,

c.`name`

FROM

`select`se

JOIN`course`cONse.`c_id`= c.`id`

) eONs.`id`=e.`stu_id`

SELECT

*

FROM

`student`s

WHERE

s.`dep_id`= (

SELECT

`id`

FROM

`department`d

WHERE

d.`name`='外国语学院'

)

在这两个例子中,第一个SQL中的子表只会被查询一次,但是在第二个SQL中,子表会被执行n次,这个n取决student表中的数据条数,如果子表的数据量很大的话,那么SQL的执行速度会十分慢。

这是典型的通过执行顺序来优化SQL,除此之外,要想SQL执行快一点,应该尽量避免模糊匹配,如:like,in,not in 等这些匹配条件。

还有几点建议给大家:

1.尽量避免整表扫描,如SELECT *

2.建立合适的索引

3.使用合适的存储引擎

4.在JOIN中,尽量用小表LEFT JOIN 大表

5.除非十分必要,尽量不要使用ORDER BY,GROUP BY 和 DISTINCT(去重),尽量用索引来代替

事务

为了保证数据库记录的更新从一个一致性状态变更为另一个一致性状态使用事务来处理是非常必要。

例:

创建一张银行账户的表

mysql> CREATE TABLE `account`(

-> `id` INT PRIMARY KEY AUTO_INCREMENT,

-> `name` VARCHAR(20) NOT NULL,

-> `balance` INT

-> );

Query OK, 0 rows affected (0.52 sec)

添加两个用户及用户的存款的信息

mysql> INSERT INTO `account`(`name`,`balance`)

->  VALUES('shangdian',10000),

->        ('xiaoming',2000)

-> ;

Query OK, 2 rows affected (0.09 sec)

Records: 2  Duplicates: 0  Warnings: 0

假设现在用户小明在商店买了500元东西,现在要转账给商店,那么就需要从小明的账户上减去500,然后在商店的用户上加上500,但是如果在减500的过程中出现了系统故障,再重新启动后发现小明的钱扣了,但商店却没有收到,这时候就会出现数据变动不一致。对于这种数据的修改我们需要的就是要么同时修改成功,要么同时修改失败,所以这就需要用事务来进行出来。

START TRANSACTION:开始一个新的事务

COMMIT:提交当前事务,做出永久改变

ROLLBACK:回滚当前事务,放弃修改

mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE `account`

-> SET `balance`= `balance`-50

-> WHERE `name` ='xiaoming'

-> ;

Query OK, 1 row affected (0.04 sec)

Rows matched: 1  Changed: 1  Warnings: 0

使用ROLLBACK;使数据的修改不生效,回到事务前的状态:

mysql> ROLLBACK;

Query OK, 0 rows affected (0.06 sec)

做一次正确的操作:

mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE `account`

-> SET `balance`=`balance`-50

-> WHERE `name`='xiaoming'

-> ;

Query OK, 1 row affected (0.03 sec)

Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE `account`

-> SET `balance`=`balance`+50

->

-> WHERE `name`='shangdian'

-> ;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM `account`;

mysql> COMMIT;

Query OK, 0 rows affected (0.07 sec)

当COMMIT后,数据修改成功,ROLLBACK也没法回到之前了。

mysql> ROLLBACK;

Query OK, 0 rows affected (0.00 sec)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值