第一章 数据库介绍

1.1 数据库介绍

1.1.1 什么是数据库

存储数据的仓库. 其本质是一个文件系统,数据库按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作。

1.1.2 数据库的存储方式

1. 数据保存在内存例如:数组,集合;new出来的对象存储在堆中.堆是内存中的一小块空间优点:内存速度快 缺点:断电/程序退出,数据就清除了.内存价格贵

2. 数据保存在普通文件 优点:永久保存 缺点:查找,增加,修改,删除数据比较麻烦,效率低

3. 数据保存在数据库 优点:永久保存,通过SQL语句比较方便的操作数据库

1.2 数据库的优点

数据库是按照特定的格式将数据存储在文件中,通过SQL语句可以方便的对大量数据进行增、删、改、查操作,数据库是对大量的信息进行管理的高效的解决方案

1.3 数据库管理系统

数据库管理系统(DataBase Management System,DBMS):指一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中表内的数据

1.4 数据库管理系统、数据库和表的关系

数据库管理程序(DBMS)可以管理多个数据库,一般开发人员会针对每一个应用创建一个数据库。为保存应用中实体的数据,一般会在数据库创建多个表,以保存程序中实体的数据。数据库管理系统、数据库和表的关系如图所示:

先有数据库 → 再有表 → 再有数据 一个库包含多个表

1.5 实体类与表的对应关系

1.6 常见数据库

MYSQL:开源免费的数据库,小型的数据库.已经被Oracle收购了.MySQL6.x版本也开始收费。 Oracle:收费的大型数据库,Oracle公司的产品。Oracle收购SUN公司,收购MYSQL。 DB2 :IBM公司的数据库产品,收费的。常应用在银行系统中. SQLServer:MicroSoft 公司收费的中型的数据库。C#、.net等语言常使用。 SyBase:已经淡出历史舞台。提供了一个非常专业数据建模的工具PowerDesigner。 SQLite: 嵌入式的小型数据库,应用在手机端。

常用数据库:MYSQL,Oracle 在web应用中,使用的最多的就是MySQL数据库,原因如下:

1. 开源、免费

2. 功能足够强大,足以应付web应用开发

第二章 MySQL的安装 卸载与使用

2.1 数据库启动

MySQL启动方式和普通的windows程序双击启动方式不同,分为以下2种:

1. Windows服务方式启动 操作步骤:

2. DOS命令方式启动 操作步骤:

启动MYSQL: net start mysql 停止MYSQL: net stop mysql

2.2 控制台连接数据库

MySQL是一个需要账户名密码登录的数据库,登陆后使用,它提供了一个默认的root账号,使用安装时设置的密码即可登录,常见的登录方式有以下几种:掌握其中一种即可

1. 登录格式1:mysql -u用户名 -p密码 例如:mysql –uroot -proot

后输入密码方式:

mysql -u用户名 -p回车

密码

2. 登录格式2:mysql -hip地址 -u用户名 -p密码 例如:mysql –h127.0.0.1 –uroot -proot

3. 登录格式3:mysql --host=ip地址 --user=用户名 --password=密码 例如:mysql --host=localhost --user=root --password=root

退出MySQL:exit

第三章 SQL语句

3.1 SQL的概念

3.1.1 什么是SQL

结构化查询语言(Structured Query Language)简称SQL,SQL语句就是对数据库进行操作的一种语言。

3.1.2 SQL作用

通过SQL语句我们可以方便的操作数据库中的数据、表、数据库。 SQL是数据库管理系统都需要遵循的规范。不同的数据库生产厂商都支持SQL语句,但都有特有内容。

3.1.3 SQL语句分类

1. DDL(Data Definition Language)数据定义语言 用来定义数据库对象:数据库,表,列等。关键字:create,drop,alter等

2. DML(Data Manipulation Language)数据操作语言 用来对数据库中表的数据进行增删改。关键字:insert,delete, update等

3. DQL(Data Query Language) 数据查询语言 (掌握)DQL语言并不是属于MYSQL官方的分类,但是对数据库的操作最多就是查询,所以我们的程序员把查询语句的语句称作为DQL语言

4. DCL(Data Control Language)数据控制语言(了解)用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE等

5. TCL(Transaction Control Language) 事务控制语言用于控制数据库的事务操作,关键字; COMMIT,SAVEPOINT,ROLLBACK等

3.2SQL通用语法

1. SQL语句可以单行或多行书写,以分号结尾。

2. 可使用空格和缩进来增强语句的可读性。

3. MySQL数据库的SQL语句不区分大小写,关键字建议使用大写。

SELECT * FROM student;

4. 3种注释 单行注释: -- 注释内容 或 # 注释内容(mysql特有) 多行注释: /* 注释 */

3.3DDL语句

3.3.1DDL操作数据库

创建数据库

1. 直接创建数据库 CREATE DATABASE 数据库名;

2. 判断是否存在并创建数据库(了解) CREATE DATABASE IF NOT EXISTS 数据库名;

3. 创建数据库并指定字符集(了解) CREATE DATABASE 数据库名 CHARACTER SET 字符集;4. 具体操作:直接创建数据库db1

CREATE DATABASE db1;

判断是否存在并创建数据库db2

SELECT * FROM student;CREATE DATABASE db1;CREATE DATABASE IF NOT EXISTS db2;

创建数据库并指定字符集为gbk

CREATE DATABASE db2 CHARACTER SET gbk;

查看数据库

1. 查看所有的数据库

SHOW databases;

2. 查看某个数据库的定义信息

SHOW CREATE DATABASE 数据库名;

修改数据库(了解)

修改数据库字符集格式

ALTER DATABASE 数据库名 DEFAULT CHARACTER SET 字符集;

具体操作:

将db3数据库的字符集改成utf8

CREATE DATABASE db2 CHARACTER SET gbk;ALTER DATABASE db3 DEFAULT CHARACTER SET utf8;

删除数据库

DROP DATABASE 数据库名;

具体操作:

删除db2数据库

DROP DATABASE db2;

使用数据库

1. 查看正在使用的数据库

SELECT DATABASE();

2. 使用/切换数据库 USE 数据库名;

具体操作:查看正在使用的数据库

SELECT DATABASE();

使用db1数据库

USE db1;

3.3.2 DDL操作表

创建表

前提先使用某个数据库

创建表 CREATE TABLE 表名 (字段名1 字段类型1, 字段名2 字段类型2…);

建议写成如下格式:

CREATE TABLE 表名 (

字段名1 字段类型1,

字段名2 字段类型2

);

MySQL数据类型 MySQL中的我们常使用的数据类型如下:

详细的数据类型如下(不建议详细阅读!)

创建student表包含id,name,birthday字段

CREATE TABLE student (

id INT,

name VARCHAR(20),

birthday DATE

);

查看表

1. 查看某个数据库中的所有表

SHOW TABLES;

2. 查看表结构

DESC 表名;

3. 查看创建表的SQL语句

SHOW CREATE TABLE 表名;

具体操作:

查看mysql数据库中的所有表

SHOW TABLES;

查看student表的结构

DESC student;

查看student的创建表SQL语句

SHOW CREATE TABLE student;

快速创建一个表结构相同的表

CREATE TABLE 新表名 LIKE 旧表名;

具体操作:

创建s1表,s1表结构和student表结构相同

CREATE TABLE S1 LIKE STUDENT;

删除表

1. 直接删除表 DROP TABLE 表名;

2. 判断表是否存在并删除表(了解) DROP TABLE IF EXISTS 表名;

具体操作:

直接删除表s1表

DROP TABLE s1;

判断表是否存在并删除s1表

DROP TABLE IF EXISTS s1;

修改表结构

修改表结构使用不是很频繁,只需要知道下,等需要使用的时候再回来查即可

1. 添加表列 ALTER TABLE 表名 ADD 列名 类型;

具体操作:

为学生表添加一个新的字段remark,类型为varchar(20)

ALTER TABLE student ADD remark VARCHAR(20);

2. 修改列类型 ALTER TABLE 表名 MODIFY 列名 新的类型;

具体操作:将student表中的remark字段的改成varchar(100)

ALTER TABLE student MODIFY remark VARCHAR(100);

3. 修改列名 ALTER TABLE 表名 CHANGE 旧列名 新列名 类型;

具体操作:将student表中的remark字段名改成intro,类型varchar(30)

ALTER TABLE student CHANGE remark intro varchar(30);

4. 删除列 ALTER TABLE 表名 DROP 列名;

具体操作:删除student表中的字段intro

ALTER TABLE student DROP intro;

5. 修改表名 RENAME TABLE 表名 TO 新表名;

具体操作:将学生表student改名成student2

RENAME TABLE student TO student2;

6. 修改字符集 ALTER TABLE 表名 character set 字符集;

具体操作:将sutden2表的编码修改成gbk

ALTER TABLE student2 character set gbk;

3.4 DML语句

3.4.1插入记录

插入全部字段

插入全部字段

所有的字段名都写出来

INSERT INTO 表名 (字段名1, 字段名2, 字段名3…) VALUES (值1, 值2, 值3);

不写字段名 INSERT INTO 表名 VALUES (值1, 值2, 值3…);

插入部分字段

插入部分数据

INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...); 没有添加数据的字段会使用NULL

1. 关键字说明

INSERT INTO 表名 – 表示往哪张表中添加数据(字段名1, 字段名2, …) ‐‐ 要给哪些字段设置值VALUES (值1, 值2, …); ‐‐ 设置具体的值

2. 注意

值与字段必须对应,个数相同,

类型相同值的数据大小必须在字段的长度范围内

除了数值类型外,其它的字段类型的值必须使用引号引起。(建议单引号)

如果要插入空值,可以不写字段,或者插入null

3. 具体操作:插入部分数据,往学生表中添加 id, name, age, sex数据

INSERT INTO student (id, NAME, age, sex) VALUES (1, '张三', 20, '男');

向表中插入所有字段

所有的字段名都写出来

INSERT INTO student (NAME, id, age, sex, address) VALUES ('李四', 2, 23, '女', '广州');

不写字段名

INSERT INTO student VALUES (3, '王五', 18, '男', '北京');

DOS命令窗口操数据库乱码

当我们使用DOS命令行进行SQL语句操作如有有中文会出现乱码,导致SQL执行失败

错误原因:因为MySQL的客户端设置编码是utf8,而系统的DOS命令行编码是gbk,编码不一致导致的乱码

查看 MySQL 内部设置的编码 show variables like 'character%';

解决方案:修改client、connection、results的编码为GBK,保证和DOS命令行编码保持一致

1. 单独设置

set character_set_client=gbk;

set character_set_connection=gbk;

set character_set_results=gbk;

2. 快捷设置

set names gbk;

注意:以上2种方式为临时方案,退出DOS命令行就失效了,需要每次都配置

3. 修改MySQL安装目录下的my.ini文件,重启服务所有地方生效。此方案将所有编码都修改了

蠕虫复制

什么是蠕虫复制:在已有的数据基础之上,将原来的数据进行复制,插入到对应的表中 语法格式:INSERT INTO表名1 SELECT * FROM 表名2; 作用:将表名2中的数据复制到表名1中set character_set_client=gbk; set character_set_connection=gbk;set character_set_results=gbk;set names gbk;

具体操作:创建student2表,student2结构和student表结构一样

CREATE TABLE student2 LIKE student;

将student表中的数据添加到student2表中

INSERT INTO student2 SELECT * FROM student;

注意:如果只想复制student表中name,age字段数据到student2表中使用如下格式 INSERT INTOstudent2(NAME, age) SELECT NAME, age FROM student;

3.4.2更新表记录

1. 不带条件修改数据 UPDATE 表名 SET 字段名=值;

2. 带条件修改数据 UPDATE 表名 SET 字段名=值 WHERE 字段名=值;

3. 关键字说明

UPDATE: 修改数据

SET: 修改哪些字段

WHERE: 指定条件

4. 具体操作:

不带条件修改数据,将所有的性别改成女

UPDATE student SET sex='女';

带条件修改数据,将id号为2的学生性别改成男

UPDATE student SET sex='男' WHERE id=2;

一次修改多个列,把id为3的学生,年龄改成26岁,address改成北京

UPDATE student SET age=26, address='北京' WHERE id=3;

3.4.3删除表记录

1. 不带条件删除数据 DELETE FROM 表名;

2. 带条件删除数据 DELETE FROM 表名 WHERE 字段名=值;

3. truncate删除表记录 TRUNCATE TABLE 表名;

truncate和delete的区别:

delete是将表中的数据一条一条删除

truncate是将整个表摧毁,重新创建一个新的表,新的表结构和原来表结构一模一样

4. 具体操作:

带条件删除数据,删除id为3的记录

DELETE FROM student WHERE id=3;

不带条件删除数据,删除表中的所有数据

DELETE FROM student;

3.5DQL

查询不会对数据库中的数据进行修改.只是一种显示数据的方式 准备数据

CREATE TABLE student3 (

id int, name varchar(20),

age int, sex varchar(5),

address varchar(100),

math int, english int

);

INSERT INTO student3(id,NAME,age,sex,address,math,english) VALUES (1,'马云',55,'男','杭州',66,78),(2,'马化腾',45,'女','深圳',98,87),(3,'马景涛',55,'男','香港',56,77),(4,'柳岩',20,'女','湖南',76,65),(5,'柳青',20,'男','湖南',86,NULL),(6,'刘德华',57,'男','香港',99,99),(7,'马德',22,'女','香港',99,99),(8,'德玛西亚',18,'男','南京',56,65);

3.5.1简单查询

查询表所有数据

1. 使用*表示所有列 SELECT * FROM 表名; 具体操作:

SELECT * FROM student3;

2. 写出查询每列的名称 SELECT 字段名1, 字段名2, 字段名3, ... FROM 表名; 具体操作:

SELECT id, NAME ,age, sex, address, math, english FROM student3;

查询指定列

查询指定列的数据,多个列之间以逗号分隔 SELECT 字段名1, 字段名2... FROM 表名;

具体操作: 查询student3表中的id , name , age , sex , address 列

SELECT id, NAME ,age, sex, address FROM student3;

别名查询

1. 查询时给列、表指定别名需要使用AS关键字

2. 使用别名的好处是方便观看和处理查询到的数据 SELECT 字段名1 AS 别名, 字段名2 AS 别名... FROM 表名;

SELECT 字段名1 AS 别名, 字段名2 AS 别名... FROM 表名 AS 表别名;

注意:

查询给表取别名目前还看不到效果,需要到多表查询的时候才能体现出好处 AS关键字可以省略

3. 具体操作:查询sudent3表中name 和 age 列,name列的别名为”姓名”,age列的别名为”年龄”

SELECT NAME AS 姓名,age 年龄 FROM student3;

查询sudent3表中name和age列,student3表别名为s

SELECT NAME, age FROM student3 AS s;

查询给表取别名目前还看不到效果,需要到多表查询的时候才能体现出好处

清除重复值

为了演示重复值,我们再插入一条记录,

INSERT INTO student3 (id,NAME,age) VALUES(9,'马云',12);

1. 查询指定列并且结果不出现重复数据 SELECT DISTINCT 字段名 FROM 表名;

2. 具体操作:

查询name列并且结果不出现重复name

查询name,age列并且结果不出现重复name和age

SELECT DISTINCT NAME, age FROM student3;

测试完成之后 , 把刚刚插入的记录删除DELETE FROM student3 WHERE id = 9;

查询结果参与运算

1. 某列数据和固定值运算 SELECT 列名1 + 固定值 FROM 表名;

2. 某列数据和其他列数据参与运算 SELECT 列名1 + 列名2 FROM 表名;

注意: 参与运算的必须是数值类型

3. 具体例子:查询每个人的总成绩

SELECT NAME, math + english FROM student3;

结果确实将每条记录的math和english相加,有两个小问题

1.效果不好看

2.柳青的成绩为null我们来把这两个问题解决下

查询math + english的和使用别名”总成绩”

SELECT NAME, math + english 总成绩 FROM student3;

null值处理

注意 : null参与算术运算结果还是null.

ifnull(表达式1,表达式2) : 若表达式1的值为null,则返回表达式2的结果;若表达式1的值不为null,则返回表达式1的值因为english一列中有null值 , 我们可以使用ifnull解决 , 写法ifnull(english,0), 意思为若english值为null , 按0处理 ; 否则还是使用原来english的值.

SELECT NAME, math + IFNULL(english,0) 总成绩 FROM student3;

查询所有列与math + english的和并使用别名”总成绩”

SELECT *, math + IFNULL(english,0) 总成绩 FROM student3;

查询姓名、年龄,将每个人的年龄增加10岁

SELECT NAME, age + 10 FROM student3;

第四章 DQL语句

4.1条件查询

4.1.1 比较运算符

>大于 <小于 <=小于等于 >=大于等于 =等于 <>、!=不等于

具体操作:查询math分数大于80分的学生

SELECT * FROM student3 WHERE math>80;

查询english分数小于或等于80分的学生

SELECT * FROM student3 WHERE english<=80;

查询age等于20岁的学生

SELECT * FROM student3 WHERE age=20;

查询age不等于20岁的学生

SELECT * FROM student3 WHERE age!=20;

SELECT * FROM student3 WHERE age<>20;

4.1.2 逻辑运算符

and(&&) 多个条件同时满足 or(||) 多个条件其中一个满足 not(!) 不满足

具体操作:查询age大于35且性别为男的学生(两个条件同时满足)

SELECT * FROM student3 WHERE age>35 AND sex='男';

查询age大于35或性别为男的学生(两个条件其中一个满足)

SELECT * FROM student333 WHERE age>35 OR sex='男';

查询id是1或3或5的学生

SELECT * FROM student3 WHERE id=1 OR id=3 OR id=5;

in关键字 语法格式:SELECT 字段名 FROM 表名 WHERE 字段 in (数据1, 数据2...); in里面的每个数据都会作为一次条件,只要满足条件的就会显示

具体操作:查询id是1或3或5的学生

SELECT * FROM student3 WHERE id IN (1,3,5);

查询id不是1或3或5的学生

SELECT * FROM student3 WHERE id NOT IN (1,3,5);

4.1.3 范围

BETWEEN 值1 AND 值2 表示从值1到值2范围,包头又包尾 比如:age BETWEEN 80 AND 100 相当于: age>=80 &&age<=100

具体操作:查询english成绩大于等于75,且小于等于90的学生

SELECT * FROM student3 WHERE english>=75 AND english<=90;

SELECT * FROM student3 WHERE english BETWEEN 75 AND 90;

4.1.4 like

LIKE表示模糊查询 SELECT * FROM 表名 WHERE 字段名 LIKE '通配符字符串'; 满足通配符字符串规则的数据就会显示出来 所谓的通配符字符串就是含有通配符的字符串 MySQL通配符有两个: %: 表示0个或多个字符(任意个字符) _: 表示一个字符

具体操作:查询姓马的学生

SELECT * FROM student3 WHERE NAME LIKE '马%';

查询姓名中包含'德'字的学生

SELECT * FROM student3 WHERE NAME LIKE '%德%';

查询姓马,且姓名有三个字的学生

SELECT * FROM student3 WHERE NAME LIKE '马__';

4.2排序

通过ORDER BY子句,可以将查询出的结果进行排序(排序只是显示方式,不会影响数据库中数据的顺序) SELECT字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名 [ASC|DESC]; ASC: 升序, 默认是升序 DESC: 降序

4.2.1单列排序

单列排序就是使用一个字段排序

具体操作:查询所有数据,使用年龄降序排序

SELECT * FROM student3 ORDER BY age DESC;

4.2.2组合排序

组合排序就是先按第一个字段进行排序,如果第一个字段相同,才按第二个字段进行排序,依次类推。 上面的例子中,年龄是有相同的。当年龄相同再使用math进行排序 SELECT 字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名1 [ASC|DESC], 字段名2 [ASC|DESC];

具体操作:查询所有数据,在年龄降序排序的基础上,如果年龄相同再以数学成绩降序排序

SELECT * FROM student3 ORDER BY age DESC, math DESC;

4.3 聚合函数

之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个结果值。另外聚合函数会忽略空值

五个聚合函数: count: 统计指定列记录数,记录为NULL的不统计 sum: 计算指定列的数值和,如果不是数值类型,那么计算结果为0 max: 计算指定列的最大值 min: 计算指定列的最小值 avg: 计算指定列的平均值,如果不是数值类型,那么计算结果为0

聚合函数的使用:写在 SQL语句SELECT后 字段名的地方 SELECT 字段名... FROM 表名; SELECT COUNT(age)FROM 表名;

具体操作:查询学生总数

SELECT COUNT(english) FROM student3;

我们发现对于NULL的记录不会统计

我们可以利用IFNULL()函数,如果记录为NULL,给个默认值,这样统计的数据就不会遗漏

ELECT COUNT(IFNULL(english,0)) FROM student3;

SELECT COUNT(*) FROM student3;

查询年龄大于40的总数

SELECT COUNT(*) FROM student3 WHERE age>40;

查询数学成绩总分

SELECT SUM(math) FROM student3;

查询数学成绩平均分

SELECT AVG(math) FROM student3;

查询数学成绩最高分

SELECT MAX(math) FROM student3;

查询数学成绩最低分

SELECT MIN(math) FROM student3;

4.4 分组

分组查询是指使用 GROUP BY语句对查询信息进行分组,相同数据作为一组 SELECT 字段1,字段2... FROM 表名GROUP BY 分组字段 [HAVING 条件];GROUP BY怎么分组的?将分组字段结果中相同内容作为一组 SELECT * FROM student3 GROUP BY sex;这句话会将sex相同的数据作为一组

GROUP BY将分组字段结果中相同内容作为一组,并且返回每组的第一条数据,所以单独分组没什么用处。分组的目的就是为了统计,一般分组会跟聚合函数一起使用。分组后聚合函数的作用?不是操作所有数据,而是操作一组数据。 SELECT SUM(math), sex FROM student3 GROUPBY sex; 效果如下:

实际上是将每组的math进行求和,返回每组统计的结果

注意事项:当我们使用某个字段分组,在查询的时候也需要将这个字段查询出来,否则看不到数据属于哪组的查询的时候没有查询出分组字段

查询的时候查询出分组字段

具体步骤:按性别分组

SELECT sex FROM student3 GROUP BY sex;

查询男女各多少人

1.查询所有数据,按性别分组。 2.统计每组人数SELECT sex, COUNT(*) FROM student3 GROUP BY sex;

查询年龄大于25岁的人,按性别分组,统计每组的人数

1.先过滤掉年龄小于25岁的人。2.再分组。3.最后统计每组的人数SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex;

查询年龄大于25岁的人,按性别分组,统计每组的人数,并只显示性别人数大于2的数据 有很多同学可能会将SQL语句写出这样:

SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex WHERE COUNT(*) >2;

注意: 并只显示性别人数>2的数据属于分组后的条件,对于分组后的条件需要使用having子句

SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex HAVING COUNT(*) >2;只有分组后人数大于2的`男`这组数据显示出来

having与where的区别

having是在分组后对数据进行过滤.

where是在分组前对数据进行过滤

having后面可以使用聚合函数

where后面不可以使用聚合函数

准备数据:

INSERT INTO student3(id,NAME,age,sex,address,math,english) VALUES (9,'唐僧',25,'男','长安',87,78),(10,'孙悟空',18,'男','花果山',100,66),(11,'猪八戒',22,'男','高老庄',58,78),(12,'沙僧',50,'男','流沙河',77,88),(13,'白骨精',22,'女','白虎岭',66,66),(14,'蜘蛛精',23,'女','盘丝洞',88,88);

4.5 limit语句

LIMIT是限制的意思,所以LIMIT的作用就是限制查询记录的条数。 SELECT *|字段列表 [as 别名] FROM 表名[WHERE子句] [GROUP BY子句][HAVING子句][ORDER BY子句][LIMIT子句]; 思考:limit子句为什么排在最后? 因为前面所有的限制条件都处理完了,只剩下显示多少条记录的问题了!

LIMIT语法格式: LIMIT offset,length; 或者limit length; offset是指偏移量,可以认为是跳过的记录数量,默认为0 length是指需要显示的总记录数

具体步骤:查询学生表中数据,从第三条开始显示,显示6条

我们可以认为跳过前面2条,取6条数据

SELECT * FROM student3 LIMIT 2,6;

LIMIT的使用场景:分页 比如我们登录京东,淘宝,返回的商品信息可能有几万条,不是一次全部显示出来。是一页显示固定的条数。 假设我们一每页显示5条记录的方式来分页,SQL语句如下:

‐ 每页显示5条

‐‐ 第一页: LIMIT 0,5; 跳过0条,显示5条

‐‐ 第二页: LIMIT 5,5; 跳过5条,显示5条

‐‐ 第三页: LIMIT 10,5; 跳过10条,显示5条

SELECT * FROM student3 LIMIT 0,5;SELECT * FROM student3 LIMIT 5,5;SELECT * FROM student3 LIMIT 10,5;

注意:

如果第一个参数是0可以简写:

SELECT * FROM student3 LIMIT 0,5;

SELECT * FROM student3 LIMIT 5;

LIMIT 10,5; -- 不够5条,有多少显示多少

第五章 数据库备份

5.1 备份应用场景

在服务器进行数据传输、数据存储和数据交换,就有可能产生数据故障。比如发生意外停机或存储介质损坏。这时,如果没有采取数据备份和数据恢复手段与措施,就会导致数据的丢失,造成的损失是无法弥补与估量的。

5.2 source命令备份与还原

备份格式: mysqldump -u用户名 -p密码 数据库 > 文件的路径

还原格式: SOURCE 导入文件的路径;

注意:还原的时候需要先登录MySQL,并选中对应的数据库

具体操作:备份day22数据库中的数据

mysqldump ‐uroot ‐proot day22 > C:\work\课改\MYSQL课改资料\Day02‐MYSQL多表查询\code\bak.sql

数据库中的所有表和数据都会导出成SQL语句

还原day22数据库中的数据

删除day22数据库中的所有表

登录MySQL

mysql ‐uroot ‐proot

选中数据库

use day22;

select database();

使用SOURCE命令还原数据

source C:\work\课改\MYSQL课改资料\Day02‐MYSQL多表查询\code\bak.sql

5.3 图形化界面备份与还原

备份day22数据库中的数据

包含创建数据库的语句 

还原day22数据库中的数据

删除day22数据库

数据库列表区域右键“执行SQL脚本”, 指定要执行的SQL文件,执行即可

第六章 数据库约束

对表中的数据进行进一步的限制,保证数据的正确性、有效性和完整性。 约束种类:

PRIMARY KEY: 主键

UNIQUE: 唯一

NOT NULL: 非空

DEFAULT: 默认

FOREIGN KEY: 外键

6.1 主键

6.1.1 主键作用

用来唯一标识一条记录,每个表都应该有一个主键,并且每个表只能有一个主键。 有些记录的 name,age,score 字段的值都一样时,那么就没法区分这些数据,造成数据库的记录不唯一,这样就不方便管理数据

哪个字段应该作为表的主键? 通常不用业务字段作为主键,单独给每张表设计一个id的字段,把id作为主键。主键是给数据库和程序使用的,不是给最终的客户使用的。所以主键有没有含义没有关系,只要不重复,非空就行。

6.1.2 创建主键

主键:PRIMARY KEY 主键的特点:

主键必须包含唯一的值

主键列不能包含NULL值

创建主键方式:

1. 在创建表的时候给字段添加主键

字段名 字段类型 PRIMARY KEY

2. 在已有表中添加主键 ALTER TABLE 表名 ADD PRIMARY KEY(字段名);

具体操作:创建表学生表st5, 包含字段(id, name, age)将id做为主键

CREATE TABLE st5 (

id INT PRIMARY KEY, ‐‐ id是主键 NAME VARCHAR(20),

age INT

);

添加数据

INSERT INTO st5 (id, NAME) VALUES (1, '唐伯虎');

INSERT INTO st5 (id, NAME) VALUES (2, '周文宾');

INSERT INTO st5 (id, NAME) VALUES (3, '祝枝山');

INSERT INTO st5 (id, NAME) VALUES (4, '文征明');

插入重复的主键值

主键是唯一的不能重复:

Duplicate entry '1' for key 'PRIMARY'INSERT INTO st5 (id, NAME) VALUES (1, '文征明2');

插入NULL的主键值

主键是不能为空的:

Column 'id' cannot be nullINSERT INTO st5 (id, NAME) VALUES (NULL, '文征明3')

注意 : 一张表中只有一个主键 , 主键可以为多个字段 , 不过我们一般增减一个字段 id 来作为主键.

6.1.3 删除主键

ALTER TABLE 表名 DROP PRIMARY KEY;

具体操作:删除st5表的主键

ALTER TABLE st5 DROP PRIMARY KEY;

6.1.4 主键自增

主键如果让我们自己添加很有可能重复,我们通常希望在每次插入新记录时,数据库自动生成主键字段的值AUTO_INCREMENT 表示自动增长(字段类型是整型数字)

具体操作:创建学生表st6, 包含字段(id, name, age)将id做为主键并自动增长

CREATE TABLE st6 (

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

age INT

);

插入数据

主键默认从1开始自动增长

INSERT INTO st6 (NAME, age) VALUES ('唐僧', 22);

INSERT INTO st6 (NAME, age) VALUES ('孙悟空', 26);

INSERT INTO st6 (NAME, age) VALUES ('猪八戒', 25);

INSERT INTO st6 (NAME, age) VALUES ('沙僧', 20);

DELETE和TRUNCATE的区别

DELETE 删除表中的数据,但不重置AUTO_INCREMENT的值。

TRUNCATE 摧毁表,重建表,AUTO_INCREMENT重置为1

6.2 唯一

在这张表中这个字段的值不能重复

6.2.1唯一约束

字段名 字段类型 UNIQUE

6.2.2 实现唯一约束

具体步骤:创建学生表st7, 包含字段(id, name),name这一列设置唯一约束,不能出现同名的学生

CREATE TABLE st7 (

id INT,

NAME VARCHAR(20) UNIQUE

);

添加一个学生

INSERT INTO st7 VALUES (1, '貂蝉');

INSERT INTO st7 VALUES (2, '西施');

INSERT INTO st7 VALUES (3, '王昭君');

INSERT INTO st7 VALUES (4, '杨玉环');

‐‐ 插入相同的名字出现name重复: Duplicate entry '貂蝉' for key 'name'

INSERT INTO st7 VALUES (5, '貂蝉'); ‐‐ 出现多个null的时候会怎样?因为null是没有值,所以不存在重复的问题

INSERT INTO st3 VALUES (5, NULL);INSERT INTO st3 VALUES (6, NULL);

6.3 非空

这个字段必须设置值,不能是NULL

6.3.1 非空约束的基本语法格式

字段名 字段类型 NOT NULL

具体操作:创建表学生表st8, 包含字段(id,name,gender)其中name不能为NULL

CREATE TABLE st8 (

id INT,

NAME VARCHAR(20) NOT NULL, gender CHAR(2)

);

添加一条完整的记录

INSERT INTO st8 VALUES (1, '郭富城', '男');

INSERT INTO st8 VALUES (2, '黎明', '男');

INSERT INTO st8 VALUES (3, '张学友', '男');

INSERT INTO st8 VALUES (4, '刘德华', '男');

‐‐ 姓名不赋值出现姓名不能为null: Column 'name' cannot be null

INSERT INTO st8 VALUES (5, NULL, '男');

6.3.2 默认值

往表中添加数据时,如果不指定这个字段的数据,就使用默认值默认值格式 字段名 字段类型 DEFAULT 默认值

具体步骤:创建一个学生表 st9,包含字段(id,name,address), 地址默认值是广州

CREATE TABLE st9 (

id INT,

NAME VARCHAR(20), address VARCHAR(50) DEFAULT '广州'

)

添加一条记录,使用默认地址

INSERT INTO st9 (id, NAME) VALUES (1, '刘德华');

添加一条记录,不使用默认地址

INSERT INTO st9 VALUES (2, '张学友', '香港');

第七章 表关系

7.1 表关系概念图

现实生活中,实体与实体之间肯定是有关系的,比如:老公和老婆,部门和员工,老师和学生等。那么我们在设计表的时候,就应该体现出表与表之间的这种关系!分成三种:

1. 一对一

2. 一对多

3. 多对多

7.2 一对多

对多(1:n) 例如:班级和学生,部门和员工,客户和订单,分类和商品 一对多建表原则: 在从表(多方)创建一个字段,指向主表(一方)的主键.我们把这个字段称之为外键.

7.3 多对多

多对多(m:n) 例如:老师和学生,学生和课程,用户和角色 多对多关系建表原则: 需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键。

7.4 一对(了解)

对一(1:1) 在实际的开发中应用不多.因为一对一可以创建成一张表。 两种建表原则:

外键唯一:主表的主键和从表的外键(唯一),形成主外键关系,

外键唯一UNIQUE外键是主键:主表的主键和从表的主键,形成主外键关系

7.5 外键约束

7.5.1 什么是外键约束

一张表中的某个字段引用另一个表的主键 主表: 约束别人 副表/从表: 使用别人的数据,被别人约束

7.5.2 创建外键

1. 新建表时增加外键: [CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)

关键字解释:

CONSTRAINT -- 约束关键字

FOREIGN KEY(外键字段名) –- 某个字段作为外键

REFERENCES -- 主表名(主键字段名) 表示参照主表中的某个字段

2.已有表增加外键: ALTER TABLE 从表 ADD [CONSTRAINT] [外键约束名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主键字段名);

具体操作:以"新建表时添加外键"演示

‐ 先创建部门表

CREATE TABLE department (

id INT PRIMARY KEY AUTO_INCREMENT,

dep_name VARCHAR(20),

dep_location VARCHAR(20)

);

‐‐ 添加2个部门

INSERT INTO department (dep_name, dep_location) VALUES ('研发部', '广州'), ('销售部', '深圳');

‐‐ 然后创建员工表,添加外键约束

CREATE TABLE employee (

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

age INT, dep_id INT,

‐‐ 添加一个外键 ‐‐ 外键取名公司要求,一般fk结尾 CONSTRAINT         emp_depid_ref_dep_id_fk FOREIGN KEY(dep_id) REFERENCES department(id)

);

正常添加数据

INSERT INTO employee (NAME, age, dep_id) VALUES('张三', 20, 1),('李四', 21, 1),('王五', 20, 1),('老王', 20, 2),('大王', 22, 2),('小王', 18, 2);

部门错误的数据添加失败

INSERT INTO employee (NAME, age, dep_id) VALUES ('二王', 20, 5);

7.5.3 删除外键(了解)

ALTER TABLE 从表 drop foreign key 外键名称;

具体操作:删除employee表的emp_depid_ref_dep_id_fk外键

ALTER TABLE employee DROP FOREIGN KEY emp_depid_ref_dep_id_fk;

在employee表情存在况下添加外键

ALTER TABLE employee ADD CONSTRAINT emp_depid_ref_dep_id_fk FOREIGN KEY(dep_id) REFERENCES department(id);

第八章 三范式

8.1 什么是范式

范式是指:设计数据库表的规则(Normal Form) 好的数据库设计对数据的存储性能和后期的程序开发,都会产生重要的影响。建立科学的,规范的数据库就需要满足一些规则来优化数据的设计和存储

8.2 范式的基本分类

目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。

8.3 第一范式

即数据库表的每一列都是不可分割的原子数据项,而不能是集合、数组、记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中每个列的值只能是表的一个属性或一个属性的一部分。简而言之,第一范式每一列不可再拆分,称为原子性。 第一范式:每一列不能再拆分

总结:如果不遵守第一范式,查询出数据还需要进一步处理(查询不方便)。遵守第一范式,需要什么字段的数据就查询什么数据(方便查询)。

8.4 第二范式

第二范式(2NF)要求数据库表中的每个实例或记录必须可以被唯一地区分。选取一个能区分每个实体的属性或属性组,作为实体的唯一标识。例如在员工表中的身份证号码即可实现每个员工的区分,该身份证号码即为候选键,任何一个候选键都可以被选作主键。在找不到候选键时,可额外增加属性以实现区分。 第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是在第一范式的基础上属性完全依赖于主键。

第二范式:1. 一张表只描述一件事情

2. 表中的每一个字段都依赖于主键

总结:如果不准守第二范式,数据冗余,相同数据无法区分。遵守第二范式减少数据冗余,通过主键区分相同数据。

8.5 第三范式

在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖) 第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。

总结:如果不准守第三范式,可能会有相同数据无法区分,修改数据的时候多张表都需要修改(不方便修改)。遵守第三范式通过id可以区分相同数据,修改数据的时候只需要修改一张表(方便修改)。

第九章 多表查询

9.1 什么是多表查询

同时查询多张表获取到需要的数据 比如:我们想查询到开发部有多少人,需要将部门表和员工表同时进行查询

准备数据

创建部门表

CREATE TABLE dept (

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20)

);

INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');

‐‐ 创建员工表

CREATE TABLE emp (

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(10),

gender CHAR(1),

‐‐ 性别 salary DOUBLE,

‐‐ 工资 join_date DATE

, ‐‐ 入职日期 dept_id INT

);

INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013‐02‐24',1);

INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010‐12‐02',2);

INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008‐08‐08',2);

INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015‐10‐07',3);

INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011‐03‐14',1);

9.2 笛尔卡乘积现象

9.2.1 什么是笛尔卡乘积现象

多表查询时左表的每条数据和右表的每条数据组合,这种效果成为笛卡尔积需求:查询每个部门有哪些人具体操作:

SELECT * FROM dept, emp;

以上数据其实是左表的每条数据和右表的每条数据组合。左表有3条,右表有5条,最终组合后3*5=15条数据。

9.2.2 如何清除笛尔卡乘积现象

我们发现不是所有的数据组合都是有用的,只有员工表.dept_id = 部门表.id 的数据才是有用的。所以需要通过条件过滤掉没用的数据。

SELECT * FROM dept, emp WHERE emp.`dept_id`=dept.`id`;

9.3 内连接

用左边表的记录去匹配右边表的记录,如果符合条件的则显示

9.3.1 隐式内连接

隐式内连接:看不到JOIN关键字,条件使用WHERE指定 SELECT 字段名 FROM 左表, 右表 WHERE 条件;

9.3.2 显示内连接

显示内连接:使用INNER JOIN ... ON语句, 可以省略INNER SELECT 字段名 FROM 左表 INNER JOIN 右表 ON 条件;

具体操作:查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称,我们发现需要联合2张表同时才能查询出需要的数据,我们使用内连接

1. 确定查询哪些表

SELECT * FROM dept INNER JOIN emp;

1. 确定表连接条件,员工表.dept_id = 部门表.id 的数据才是有效的

SELECT * FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id`;

1. 确定表连接条件,我们查询的是唐僧的信息,部门表.name='唐僧'

SELECT * FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id` AND emp.`NAME`='唐僧';

1. 确定查询字段,查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称

SELECT emp.`id`, emp.`NAME`, emp.`gender`, emp.`salary`, dept.`NAME` FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id` AND emp.`NAME`='唐僧';

1. 我们发现写表名有点长,可以给表取别名,显示的字段名也使用别名

SELECT e.`id` 员工编号, e.`NAME` 员工姓名, e.`gender` 性别, e.`salary` 工资, d.`NAME` 部门名称 FROM dept d INNER JOIN emp e ON e.`dept_id`=d.`id` AND e.`NAME`='唐僧';

总结内连接查询步骤:

1. 确定查询哪些表

2. 确定表连接条件

3. 确定查询字段

9.4 左外连接

左外连接:使用LEFT OUTER JOIN ... ON,OUTER可以省略 SELECT 字段名 FROM 左表 LEFT OUTER JOIN 右表 ON条件; 用左边表的记录去匹配右边表的记录,如果符合条件的则显示;否则,显示NULL 可以理解为:在内连接的基础上保证左表的数据全部显示

具体操作:在部门表中增加一个销售部

INSERT INTO dept (NAME) VALUES ('销售部');

使用内连接查询

SELECT * FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id`;

使用左外连接查询

SELECT * FROM dept LEFT OUTER JOIN emp ON emp.`dept_id`=dept.`id`;

9.5 右外连接

右外连接:使用RIGHT OUTER JOIN ... ON,OUTER可以省略 SELECT 字段名 FROM 左表 RIGHT OUTER JOIN 右表ON 条件; 用右边表的记录去匹配左边表的记录,如果符合条件的则显示;否则,显示NULL 可以理解为:在内连接的基础上保证右表的数据全部显示

具体操作:

在员工表中增加一个员工 INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('沙僧','男',6666,'2013-02-24',NULL);

使用内连接查询 SELECT * FROM dept INNER JOIN emp ON emp.dept_id=dept.id;

使用右外连接查询 SELECT * FROM dept RIGHT OUTER JOIN emp ON emp.dept_id=dept.id;

呕心沥血写了三天3两夜24k字的MySQL详细教程相关推荐

  1. 两台局域网电脑大数据传输详细教程

    说到电脑间的数据传输,想必大家的脑海中立刻就会浮现出几个词,"慢"."麻烦",对于局域网内的两台电脑来说,如果是临时转移几个小文件,像是Word.PPT.PDF ...

  2. 2020mysql下载教程_Windows10 安装MySQL详细教程2020版 亲测亲写

    MYSQL安装 1.下载地址 2.安装包解压到自己Mysql目录下 本人路径:C:\Program Files\MySQL\mysql-8.0.21-winx64 3.新建my.ini文件并添加以下内 ...

  3. 安全狗+linux使用教程,三分钟秒懂!服务器linux安全狗安装详细教程

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 (nginx版)安装教程 以32位安装包为例子,64位安装包只要将对应的32改成64即可. 步骤一: 到http://safedog.cn下载软件安装包( ...

  4. [Python] 字典操作近两万字大总结(超详细教程)

  5. 两台电脑大文件传输的详细教程

    说到电脑间的数据传输,想必大家的脑海中立刻就会浮现出几个词,"慢"."麻烦",对于局域网内的两台电脑来说,如果是临时转移几个小文件,像是Word.PPT.PDF ...

  6. 聊聊在博客园写博客的这两年《Unity 3D脚本编程:使用C#语言开发跨平台游戏》正式出版...

    版本状态: 2016.9 第一次印刷 (2016.11 输出到台湾) 2017.1 第二次印刷 2017.5 第三次印刷 2017.5 电子书上线:Unity 3D脚本编程--使用C#语言开发跨平台游 ...

  7. 只因为离职报告多写这三个字,员工竟然倒赔公司2.9万!

    只因为离职报告上多写了三个字,打工人竟然要倒赔公司2.9万!是什么样的三个字有这么大的威力? 事情的经过是这样的:该员工在网上下载的离职模板基础上进行改写,文末有"请批示"三个字, ...

  8. 字字带泪——写在三十岁到来这一天

    美女CEO王潇,刚刚写了一篇三十感言.句句名言,虽然是写给女生的,但是,男生也更应该看看. <字字带泪--写在三十岁到来这一天> By 王潇 2008年11月3日 谨以此文献给我的众姐妹, ...

  9. 根据状态转移写状态机-三段式

    根据状态转移写状态机-三段式 题目描述 如图所示为两种状态机中的一种,请根据状态转移图写出代码,状态转移线上的0/0等表示的意思是过程中data/flag的值. 要求: 1. 必须使用对应类型的状态机 ...

  10. 三位数除以两位数竖式计算没有余数_苏教四上期末复习——两、三位数除以两位数...

    期末复习读万卷书 <做一好题第二单元两.三位数除以两位数 计算能力 1.竖式计算 510÷67= 409÷61= 700÷26= 291÷42= 468÷29= 810÷13= 2.简便方法计算 ...

最新文章

  1. 60颗卫星被五手火箭送上天!马斯克疯狂的卫星互联网计划不远了
  2. cannot import name filter
  3. Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制
  4. c语言vs开发小型数据库,用C语言开发小型数据库管理系统代码
  5. PHP 实现移除数组中项目为空的元素或为某值的元素
  6. Angular消息通知组件ngx-notification
  7. 灯珠电路图_可充电led台灯电路图
  8. 二重循环~~for循环
  9. 【李宏毅2020 ML/DL】P118 RL - Model-based, Meta, Multi-agent, Alpha
  10. postSQL使用触发器(trigger)分表
  11. 编译原理第二版5.1答案
  12. 全网最全leafLetAPI中文版
  13. 解决mysql闪退问题
  14. hdoj 1054 Strategic Game 最小点覆盖模版题dfs方式(Java版)
  15. 论文翻译:Dual-path RNN: efficient long sequence modeling for time-domain single-channel speech separatio
  16. 2022年王道数据结构考研复习指导习题代码(排序)
  17. 宣布造车后股价上演“过山车”,开心汽车如意算盘恐落空
  18. go-excel文档
  19. Python Turtle 小项目 8 各种音符的绘制
  20. html 按钮默认值,button_标签 | Elements_HTML_参考手册_非常教程

热门文章

  1. 贝叶斯网络之父Judea Pearl力荐、LeCun点赞,这篇长论文全面解读机器学习中的因果关系
  2. android 关闭软键盘失去焦点,Android edittext 点击其他处 失去焦点和关闭软键盘
  3. android 人物走动_Android 中通过切割图片创建人物行走动画
  4. 关于 IOS 的299$ 美元企业模式(In House)及Installing Apps Wirelessly 详解
  5. 安装gooreplacer插件为含有googlefonts api的网页提速
  6. Android基础整合项目之节日群发助手
  7. 移动端UML图应用之UML结构图——包图、部署图和组件图
  8. mhl数据线_利用MHL数据线 手机同屏到乐视电视X50air上
  9. html如何制作水滴效果图,html+css实现充电水滴融合特效代码
  10. JavaWeb实训项目案例开发之在线图书网站开发【非常适合初学者】