目录
一、SQL简述
1.SQL的概述
Structure Query Language(结构化查询语言)简称SQL,它被美国国家标准局(ANSI)确定为关系型数据库语言的美国标准,后被国际化标准组织(ISO)采纳为关系数据库语言的国际标准。数据库管理系统可以通过SQL管理数据库;定义和操作数据,维护数据的完整性和安全性。
2.SQL的优点
(1)简单易学,具有很强的操作性
(2)绝大多数重要的数据库管理系统均支持SQL
(3)高度非过程化;用SQL操作数据库时大部分的工作由DBMS自动完成
3.SQL的分类
> DDL(Data Definition Language) 数据定义语言,用来操作数据库、表、列等; 常用语句:CREATE、 ALTER、DROP
> DML(Data Manipulation Language) 数据操作语言,用来操作数据库中表里的数据;常用语句:INSERT、 UPDATE、 DELETE
> DCL(Data Control Language) 数据控制语言,用来操作访问权限和安全级别; 常用语句:GRANT、DENY
> DQL(Data Query Language) 数据查询语言,用来查询数据 常用语句:SELECT
4.数据库的三大范式
(1)第一范式(1NF)是指数据库的列是不可分割的基本数据单位,每列的值具有原子性。例如,需求如果知道省市的信息,则地址的那一列就应该拆分为更详细的省市列。
(2)第二范式(2NF)是在满足第一范式(1NF)条件下,主键以外的列必须完全依赖于主键,而不能仅依赖主键的一部分,也不能与主键没有关系。例如,订单表只描述跟订单相关的,,因此所有字段都必须与订单id 相关。
(3)第三范式(3NF)是在满足第二范式(2NF)条件下,数据不能有传递关系,即表中的非主键列必须和主键直接关系而非间接关系。例如 a --> b --> c 这种关系是不可以的。
二、数据库的数据类型
使用MySQL数据库存储数据时,不同的数据类型决定了 MySQL存储数据方式的不同。为此,MySQL数据库提供了多种数据类型,其中包括整数类型、浮点数类型、定点 数类型、日期和时间类型、字符串类型、二进制…等等数据类型。
1.整数类型
根据数值取值范围的不同MySQL 中的整数类型可分为5种,分别是
TINYINT、SMALLINT、MEDIUMINT、INT和 BIGINT
下图列举了 MySQL不同整数类型所对应的字节大小和取值范围。
数据类型 | 字节数 | 无符号数的取值范围 | 有符号数的取值范围 |
---|---|---|---|
TINYINT | 1 | 0~255 | -128~127 |
SMALLINT | 2 | 0~65535 | -32768~32768(2^15) |
MEDIUMINT | 3 | 0~16777215 | -(2^23) ~ 2^23 |
INT | 4 | 0~2^32 | -(2^31) ~ 2^31 |
BIGINT | 8 | 0~2^64 | -(2^63) ~ 2^63 |
2.浮点数类型和定点数类型
在MySQL数据库中使用浮点数和定点数来存储小数。
浮点数的类型有两种:单精度浮点数类型(FLOAT)和双精度浮点数类型(DOUBLE)。
而定点数类型只有一种即 DECIMAL 类型。
下图列举了 MySQL中浮点数和定点数类型所对应的字节大小:
数据类型 | 字节数 |
---|---|
FLOAT | 4 |
DOUBLE | 8 |
DECIMAL(M,D) | M+2 |
DECIMAL类型的取值范围与DOUBLE类型相同。但是,DECIMAL类型的有效取值范围是由M和D决定的。其中,M表示的是数据的长度,D表示的是小数点后的长度。
比如,将数据类型为DECIMAL(6,2)的数据6.5243 插入数据库后显示的结果为6.52
3.字符串类型
在MySQL中常用CHAR 和 VARCHAR 表示字符串。
CHAR 存储固定长度字符串,VARCHAR存储可变长度的字符串。
当数据为CHAR(M)类型时,所占用的存储空间都是固定M个字节;而VARCHAR(M)所对应的数据所占用的字节数为M+1,一个字节来存储长度。
数据类型 | 储存范围 |
---|---|
TINYTEXT | 0~255字节 |
TEXT | 0~65535字节 |
MEDIUMTEXT | 0~16777215字节 |
LONGTEXT | 0~4294967295字节 |
注意,所有字符串类型的数据必须用单引号,不能用双引号!
4.文本类型
文本类型用于表示大文本数据,例如,文章内容、评论、详情等,它的类型分为如下4种:
数据类型 | 储存范围 |
---|---|
TINYTEXT | 0~255字节 |
TEXT | 0~65535字节 |
MEDIUMTEXT | 0~16777215字节 |
LONGTEXT | 0~4294967295字节 |
5.日期与时间类型
MySQL提供的表示日期和时间的数据类型分别是 :YEAR、DATE、TIME、DATETIME 和 TIMESTAMP。下图列举了日期和时间数据类型所对应的字节数、取值范围、日期格式以及零值:
数据类型 | 字节数 | 取值范围 | 日期格式 | 零值 |
---|---|---|---|---|
YEAR | 1 | 1901~2155 | YYYY | 0000 |
DATE | 4 | 1000-01-01~9999-12-31 | YYYY-MM-DD | 0000-00-00 |
TIME | 3 | -838:59:59~ 838:59:59 | HH:MM:SS | 00:00:00 |
DATETIME | 8 | 1000-01-01 00:00:00~9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 0000-00-00 00:00:00 |
TIMESTAMP | 4 | 1970-01-01 00:00:01~2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 0000-00-00 00:00:00 |
5.1 YEAR类型
YEAR类型用于表示年份,在MySQL中,可以使用以下三种格式指定YEAR类型 的值。
1、使用4位字符串或数字表示,范围为’1901’—'2155’或1901—2155。例如,输人 ‘2019’或2019插人到数据库中的值均为2019。
2、使用两位字符串表示,范围为 ’00’—‘99’。其中,‘00’—'69’范围的值会被转换为 2000—2069范围的YEAR值,‘70’—'99’范围的值会被转换为1970—1999范围的YEAR 值。例如,输人’19’插人到数据库中的值为2019。
3、使用两位数字表示,范围为1—99。其中,1—69范围的值会被转换为2001— 2069范围的YEAR值,70—99范围的值会被转换为1970—1999范围的YEAR值。例 如,输入19插入到数据库中的值为2019。
请注意:当使用YEAR类型时,一定要区分’0’和 0。因为字符串格式的’0’表示的YEAR值是2000而数字格式的0表示的YEAR值是0000。
5.2 TIME类型
TIME类型用于表示时间值,它的显示形式一般为HH:MM:SS,其中,HH表示小时, MM表示分,SS表示秒。在MySQL中,可以使用以下3种格式指定TIME类型的值。
1、以’D HH:MM:SS’字符串格式表示。其中,D表示日可取0—34之间的值, 插人数据时,小时的值等于(DX24+HH)。例如,输入’2 11:30:50’插人数据库中的日期为59:30:50。
2、以’HHMMSS’字符串格式或者HHMMSS数字格式表示。 例如,输人’115454’或115454,插入数据库中的日期为11:54:54
3、使用CURRENT_TIME或NOW()输人当前系统时间。
5.3 DATETIME类型
DATETIME类型用于表示日期和时间,它的显示形式为
’YYYY-MM-DD HH: MM:SS’
其中YYYY表示年,MM表示月,DD表示日,HH表示小时,MM表示分,SS 表示秒。在MySQL中,可以使用以下4种格式指定DATETIME类型的值。
(1)以 ’YYYY-MM-DD HH:MM:SS’ 字符串格式表示的日期和时间,取值范围为’1000-01-01 00:00:00’—‘9999-12-3 23:59:59’。例如,输人’2021-01-22 09:01:23’,插入数据库中的 DATETIME 值为 2021-01-22 09:01:23。
(2)以 ’YY-MM-DD HH:MM:SS’ 字符串格式表示的日期和时间,其中YY表示年,取值范围为’00’—‘99’。与DATE类型中的YY相同,‘00’— '69’范围的值会被转换为2000—2069范围的值,‘70’—'99’范围的值会被转换为1970—1999范围的值。
(3)以YYYYMMDDHHMMSS 或者YYMMDDHHMMSS 数字格式或相应字符串表示的日期和时间。例如,插入20210122090123或者210122090123,插人数据库中的DATETIME值都 为 2021-01-22 09:01:23。
(4)使用NOW来输入当前系统的日期和时间。
5.4 TIMESTAMP类型
TIMESTAMP类型用于表示日期和时间,它的显示形式与DATETIME相同但取值范围比DATETIME小。在此,介绍几种TIMESTAMP类型与DATATIME类型不同的形式:
(1)使用CURRENT_TIMESTAMP输入系统当前日期和时间。
(2)输人NULL时系统会输入系统当前日期和时间。
(3)无任何输人时系统会输入系统当前日期和时间。
6.二进制类型
在MySQL中常用BLOB存储二进制类型的数据,例如:图片、PDF文档等。
BLOB类型分为如下四种:
数据类型 | 储存范围 |
---|---|
TINYBLOB | 0~255字节 |
BLOB | 0~65535字节 |
MEDIUMBLOB | 0~16777215字节 |
LONGBLOB | 0~4294967295字节 |
三、数据库、数据表的基本操作
1.数据库的基本操作
MySQL安装完成后,要想将数据存储到数据库的表中,首先要创建一个数据库。
(1)创建数据库就是在数据库系统中划分一块空间存储数据:
create database 数据库名称;
(2)创建一个叫db1的数据库:
show create database db1;
(3)创建数据库后查看该数据库基本信息MySQL命令:
show create database db1;
(4)删除数据库MySQL命令:
drop database db1;
(5)查询出MySQL中所有的数据库MySQL命令:
show databases;
(6)将数据库的字符集修改为gbk MySQL命令:
alter database db1 character set gbk;
(7)切换数据库:
use db1;
(8)查看当前使用的数据库:
select database();
2.数据表的基本操作
数据库创建成功后可在该数据库中创建数据表(简称为表)存储数据。
请注意:在操作数据表之前应使用“USE 数据库名;”指定操作是在哪个数据库中进行先关操作,否则会抛出“No database selected”错误。
语法如下:
create table 表名(
字段1 字段类型,
字段2 字段类型,
…
字段n 字段类型
);
2.1 创建数据表
示例:创建学生表 MySQL命令:
create table student(
id int,
name varchar(20),
gender varchar(10),
birthday date
);
2.2 查看数据表
(1)示例:查看当前数据库中所有表 MySQL命令:
show tables;
(2)示例:查表的基本信息:
show create table t_student;
(3)示例:查看表的字段信息 :
desc t_tudent;
2.3 修改数据表
有时,希望对表中的某些信息进行修改,例如:修改表名、修改字段名、修改字段 数据类型…等等。在MySQL中使用alter table修改数据表。
(1)修改表名 :
alter table t_student rename to t_stu;
(2)修改字段名 :
alter table t_stu change name sname varchar(10);
(3)修改字段数据类型:
alter table t_stu modify sname int;
(4)增加字段:
alter table t_stu add address varchar(50);
(5)删除字段 :
alter table t_stu drop address;
2.4 删除数据表
drop table t_stu;
四、数据表的约束
为防止错误的数据被插入到数据表,MySQL中定义了一些维护数据库完整性的规则;这些规则常称为表的约束。常见约束如下:
约束条件 | 说明 |
---|---|
PRIMARY KEY | 主键约束,用于唯一标识对应的记录 |
NOT NULL | 非空约束 |
DEFAULT | 默认值约束,用于设置字段的默认值 |
UNIQUE | 唯一性约束 |
FOREIGN KEY | 外键约束 |
以上五种约束条件针对表中字段进行限制从而保证数据表中数据的正确性和唯一性。换句话说,表的约束实际上就是表中数据的限制条件。
1.主键约束
主键约束即 primary key,用于唯一地标识表中的每一行。主键的数据在表中是唯一且非空。
这点类似于我们每个人都有一个身份证号,并且这个身份证号是唯一的。
主键约束基本语法:
字段名 数据类型 primary key;
设置主键约束(primary key)的第一种方式:
create table student(
id int primary key,
name varchar(20)
);
设置主键约束(primary key)的第二种方式:
create table student01(
id int,
name varchar(20),
primary key(id)
);
2.非空约束
非空约束即 NOT NULL,指的是字段的值不能为空,基本的语法格式如下所示:
字段名 数据类型 NOT NULL;
create table student02(
id int,
name varchar(20) not null
);
3.默认值约束
默认值约束即DEFAULT,用于给数据表中的字段指定默认值,即当在表中插入一条新记录时自动为这个字段插入默认值。其基本的语法格式如下所示:
字段名 数据类型 DEFAULT 默认值;
create table student03(
id int,
name varchar(20),
gender varchar(10) default 'male'
);
4.唯一性约束
唯一性约束即UNIQUE,用于保证数据表中字段的唯一性,即表中字段的值不能重复出现,其基本的语法格式如下所示:
字段名 数据类型 UNIQUE;
create table student04(
id int,
name varchar(20) unique
);
5.外键约束
外键约束即FOREIGN KEY,常用于多张表之间的约束。从表的外键,会指向主表的主键。
主表从表,也叫父表子表。
--在创建表时创建外键:
[CONSTRAINT 外键名]
FOREIGN KEY (子表外键名) REFERENCES 父表 (主键名)
-- 创建表后再增加外键:
ALTER TABLE 子表名 ADD
[CONSTRAINT 外键名]
FOREIGN KEY (子表外键名) REFERENCES 父表 (主键名);
[ ] 中括号内可以省略,如果省略了外键名,系统会自动命名。
5.1.外键约束的要求:
(1)子表里的外键通常指向父表的主键!外键的名字不能重复。
(2)数据表的存储引擎只能为InnoDB,父表和子表必须使用相同的存储引擎,而且禁止使用临时表。
(3)外键列和参照列必须具有相似的数据类型(可以相互转换),比如 int 和 tinyint 可以,而 int 和 char 则不可以。数字类型的长度以及是否有符号(是否unsigned)必须相同,字符类型的长度则可以不同。外键最好与主表主键的数据类型一致!
(4)外键列和参照列必须创建索引。如果外键列不存在索引,MySQl将自动创建。
(5)如果主表中的数据被删除或修改,那么从表中对应的数据也应该被删除或修改。必须保证数据一致性。
5.2.实战例子1:
创建父表:
CREATE TABLE teacher (
course varchar(16) NOT NULL,
teacher char(16) NOT NULL,
PRIMARY KEY (course)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建子表:(第一种创建方式)
CREATE TABLE course (
id tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
course varchar(16) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (course) REFERENCES teacher(course)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
5.3.实战例子2:
先创建一个学生表 :
create table t_student(
id int primary key,
name varchar(20)
);
创建一个班级表:
create table t_class(
classid int primary key,
studentid int
);
最后,学生表作为父表,班级表作为子表,设置外键。此时需要用第二种创建方式:
alter table t_class add constraint fk_class_studentid
foreign key(studentid) references t_stu(id);
5.4 删除外键
alter table 从表名 drop foreign key 外键名;
删除外键命令:
alter table t_class drop foreign key fk_class_studentid;
外键的那个字段不在了证明删除成功了!
五、数据表插入数据
在MySQL通过INSERT语句向数据表中插入数据。在此,我们先准备一张学生表,代码如下:
create table student(
id int,
name varchar(30),
age int,
gender varchar(30)
);
1. 为表中所有字段插入数据
每个字段名与值是严格一一对应的。每个值的顺序、类型必须与对应的字段相匹配!
但是,各字段的顺序则无须与表中定义的顺序一致,它们只要与 VALUES中值的顺序一致即可。
语法如下:
INSERT INTO 表名(字段名1,字段名2, ...)
VALUES (值 1,值 2, ...) ;
示例:向学生表中插入一条学生信息 MySQL命令:
insert into student (id,name,age,gender)
values (1,'bob',16,'male');
2. 为表中指定字段插入数据
INSERT INTO 表名(字段名1,字段名2, ...)
VALUES (值 1,值 2, ...) ;
插入数据的方法基本和为表中所有字段插入数据,一样,只是需要插入的字段由你自己指定
3. 同时插入多条记录
INSERT INTO 表名(字段名1,字段名2, ...)
VALUES (值 1,值 2, ...) , (值 1,值 2, ...), ......
(字段名1,字段名2,…) 是可选的,它用于指定插入的字段名;(值 1,值 2,…), (值 1,值 2,…)表示要插入的记录,该记录可有多条并且每条记录之间用逗号隔开。
示例:向学生表中插入多条学生信息 MySQL命令:
insert into student (id,name,age,gender)
values (2,'lucy',17,'female'),
(3,'jack',19,'male'),
(4,'tom',18,'male');
六、更新数据
在MySQL通过UPDATE语句更新数据表中的数据。
1. UPDATE基本语法
UPDATE 表名
SET 字段名1=值1 , [字段名2 =值2] ,…
[WHERE 条件表达式];
说明:字段名1、字段名2…用于指定要更新的字段名称;
值1、值 2…用于表示字段的新数据;WHERE 条件表达式是可选的,用于指定需要满足的条件。
2. UPDATE更新部分数据
示例:将某一记录的age设置为20并将其gender设置为female:
update student set age=20,gender='female'
where name='tom';
3. UPDATE更新全部数据
例如将所有记录的age设置为18:
update student set age=18;
七、删除数据
在MySQL通过DELETE语句删除数据表中的数据。
在此,我们先准备一张数据表,代码如下:
-- 创建学生表
create table student(
id int,
name varchar(30),
age int,
gender varchar(30)
);
-- 插入数据
insert into student (id,name,age,gender)
values (2,'lucy',17,'female'),
(3,'jack',19,'male'),
(4,'tom',18,'male'),
(5,'sal',19,'female'),
(6,'sun',20,'male'),
(7,'sad',13,'female'),
(8,'sam',14,'male');
1. DELETE基本语法
表名用于指定要执行删除操作的表;[WHERE 条件表达式]为可选参数,用于指定删除的条件。
DELETE FROM 表名 [WHERE 条件表达式];
2. DELETE删除部分数据
删除age等于14的所有记录:
delete from student where age=14;
3. DELETE删除全部数据
删除t_student表中的所有记录 MySQL命令:
delete from t_student;
4. TRUNCATE和DETELE的区别
TRUNCATE和DETELE都能实现删除表中的所有数据的功能,但两者也是有区别的:
(1)DELETE语句后可跟WHERE子句,可通过指定WHERE子句中的条件表达式只删除满足条件的部分记录;但是TRUNCATE语句只能用于删除表中的所有记录。
(2)使用TRUNCATE语句删除表中的数据后,再次添加记录时自增字段的初始值重新由1开始,即会重置自增字段的值;而使用DELETE语句不会重置自增字段,删除记录后再次添加记录时,自增字段会在原来最大值基础上加1。
(3)DELETE语句是DML语句,TRUNCATE语句通常被认为是DDL语句。
八、MySQL数据表简单查询
简单查询即不含where的select语句。最常用的两种查询:查询所有字段和查询指定字段。
1.查询所有字段(常用)
查询所有字段的命令:
select * from t_student;
2.查询指定字段:sid、sname
select sid,sname from t_student;
3.去除完全重复行:DISTINCT
在使用DISTINCT 时需要注意:DISTINCT关键字只能用在查询的第一个列名之前。
select distinct gender from t_student;
4.列运算
在SELECT查询语句中,数值类型的列还可以使用加减乘除运算符。
查询员工薪水的2倍:
select sname,salary*2 from t_emp;
5.常数的查询
在SELECT中除了书写列名,还可以书写常数,此时可以用于标记。
常数的查询日期标记命令:
select sid,sname,'2021-03-02' from t_student;
九、函数
(一)聚合函数
在开发中,我们常常有类似的需求:统计某个字段的最大值、最小值、 平均值等等。为此,MySQL中提供了聚合函数来实现这些功能。所谓聚合,就是将多行汇总成一行;其实,所有的聚合函数均如此——输入多行,输出一行。聚合函数具有自动滤空的功能,若某一个值为NULL,那么会自动将其过滤使其不参与运算。
聚合函数使用规则:
只有SELECT子句和HAVING子句、ORDER BY子句中能够使用聚合函数。而在WHERE子句中使用聚合函数是错误的。
1. count()函数
统计表中数据的行数或者统计指定列其值不为NULL的数据个数。
例如查询有多少该表中有多少人
select count(*) from t_student;
2. max()函数
计算指定列的最大值,如果指定列是字符串类型则使用字符串排序运算。
查询该学生表中年纪最大的学生。
select max(age) from student;
3. min()函数
计算指定列的最小值,如果指定列是字符串类型则使用字符串排序运算
查询该学生表中年纪最小的学生 MySQL命令:
select sname,min(age) from student;
4. sum()函数
计算指定列的数值和,如果指定列类型不是数值类型则计算结果为0
查询该学生表中年纪的总和 MySQL命令:
select sum(age) from student;
5. avg()函数
计算指定列的平均值,如果指定列类型不是数值类型则计算结果为
查询该学生表中年纪的平均数 MySQL命令:
select avg(age) from student;
(二)其他常用函数
1.时间函数
SELECT NOW();
SELECT DAY (NOW());
SELECT DATE (NOW());
SELECT TIME (NOW());
SELECT YEAR (NOW());
SELECT MONTH (NOW());
SELECT CURRENT_DATE();
SELECT CURRENT_TIME();
SELECT CURRENT_TIMESTAMP();
SELECT ADDTIME('14:23:12','01:02:01');
SELECT DATE_ADD(NOW(),INTERVAL 1 DAY);
SELECT DATE_ADD(NOW(),INTERVAL 1 MONTH);
SELECT DATE_SUB(NOW(),INTERVAL 1 DAY);
SELECT DATE_SUB(NOW(),INTERVAL 1 MONTH);
SELECT DATEDIFF('2019-07-22','2019-05-05');
2.字符串函数
--连接函数
SELECT CONCAT ()
--
SELECT INSTR ();
--统计长度
SELECT LENGTH();
3.数学函数
-- 绝对值
SELECT ABS(-136);
-- 向下取整
SELECT FLOOR(3.14);
-- 向上取整
SELECT CEILING(3.14);
十、条件查询
数据库中存有大量数据,我们可根据需求获取指定的数据。此时,我们可在查询语句中通过WHERE子句指定查询条件对查询结果进行过滤。
1.使用关系运算符
在WHERE中可使用关系运算符进行条件查询,常用的关系运算符如下所示:
关系运算符 | 说明 |
---|---|
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
查询年龄等于或大于17的学生的信息 MySQL命令:
select * from student where age>=17;
2.使用IN关键字
IN关键字用于判断某个字段的值是否在指定集合中,如果在指定的集合中,则将字段所在的记录将査询出来。
查询sid为S_1002和S_1003的学生信息:
select * from student where sid in ('S_1002','S_1003');
查询sid为S_1001以外的学生的信息:
select * from student where sid not in ('S_1001');
3.使用BETWEEN AND关键字
BETWEEN AND用于判断某个字段的值是否在指定的范围之内。如果字段的值在指定范围内,则将所在的记录将查询出来。
查询15到18岁的学生信息:
select * from student where age between 15 and 18;
查询不是15到18岁的学生信息 MySQL命令:
select * from student where age not between 15 and 18;
4.使用空值查询
在MySQL中,使用 IS NULL关键字判断字段的值是否为空值。请注意:空值NULL不同于0,也不同于空字符串!
查询sname不为空值的学生信息:
select * from student where sname is not null;
5.使用AND关键字
使用AND关键字可以连接两个或者多个查询条件,必须全部满足才能查询出来。
查询年纪大于15且性别为male的学生信息 MySQL命令:
select * from student
where age>15 and gender='male';
6.使用OR关键字
使用OR关键字可以连接多个査询条件,只要记录满足其中任意一个条件就会被查询出来。
查询年纪大于15或者性别为male的学生信息 MySQL命令:
select * from student
where age>15 or gender='male';
7.使用LIKE关键字
MySQL中可使用LIKE关键字可以判断两个字符串是否相匹配
7.1 普通字符串
查询sname中与wang匹配的学生信息 MySQL命令:
select * from student where sname like 'wang';
7.2 含有%通配的字符串
%用于匹配任意长度的字符串。例如,字符串“a%”匹配以字符a开始任意长度的字符串。
查询学生姓名以li开始的记录 MySQL命令:
select * from student where sname like 'li%';
查询学生姓名以g结尾的记录 MySQL命令:
select * from student where sname like '%g';
查询学生姓名包含s的记录 MySQL命令:
select * from student where sname like '%s%';
7.3 含有_通配的字符串
下划线通配符只匹配单个字符,如果要匹配多个字符,需要连续使用多个下划线通配符。
例如,字符串“ab_”匹配以字符串“ab”开始长度为3的字符串,如abc、abp等等;字符串“a__d”匹配在字符“a”和“d”之间包含两个字符的字符串,如"abcd"、"atud"等等。
查询学生姓名以zx开头且长度为4的记录:
select * from student where sname like 'zx__';
8.使用LIMIT限制查询结果的数量
查询数据时可能会返回很多条记录,而用户需要的数据可能只是其中的一条或者几条。
使用 limit m,n 或 limit n offset m 来筛选出需要的记录。
两者都表示“从m+1行开始取n行记录”。
查询学生表中年龄第三大的同学 MySQL命令:
select * from student
order by age desc #倒序
limit 2,1; #从第3个开始取1个
9.使用GROUP BY进行分组查询
GROUP BY 子句会将表中的数据进行分组,再进行查询等操作。也可以理解为,通过GROUP BY将原来的表拆分成了几张小表。
9.1 GROUP BY和聚合函数一起使用
统计各部门员工个数 MySQL命令:
select count(*), d_number from employee
group by d_number;
统计部门编号大于1001的各部门员工个数 MySQL命令:
select count(*), d_number from employee
where d_number > 1001
group by d_number;
9.2 HAVING与GROUP BY一起使用
HAVING适用于分组后再根据条件筛选,必须与GROUP BY一起使用。
统计工资总和大于8000的部门 MySQL命令:
select sum(salary),departmentnumber from employee
group by departmentnumber
having sum(salary)>8000;
10.使用ORDER BY对查询结果排序
査询出来的数据可能是无序的,我们可以使用ORDER BY对查询结果进行排序。
其语法格式如下所示:
SELECT 字段名1,字段名2,…
FROM 表名
ORDER BY 字段名1 [ASC丨DESC], 字段名2 [ASC | DESC];
参数 ASC表示升序排序(默认),DESC表示降序。
查询所有学生并按照年纪大小升序排列:
select * from student order by age asc;
查询所有学生并按照年纪大小降序排列:
select * from student order by age desc;
11.CASE WHEN语句
用于计算条件列表并返回多个可能结果表达式之一。
CASE 具有两种格式:简单 CASE 函数将某个表达式与一组简单表达式进行比较以确定结果。 CASE 搜索函数计算一组布尔表达式以确定结果。 两种格式都支持可选的 ELSE 参数。
(1)简单 CASE 函数:
CASE input_expression
WHEN when_expression THEN
result_expression [...n ]
ELSE
else_expression
END
① when_expression 是任意有效的 SQL 表达式,是 input_expression 所比较的简单表达式。两者的数据类型必须相同,或者是隐性转换。
② [...n ]占位符,表明可以使用多个 WHEN ... THEN ... 子句。
③ result_expression 是当 input_expression = when_expression 取值为 TRUE,或者 Boolean_expression 取值 TRUE 时返回的表达式。
④ else_expression 是当比较结果不为 TRUE 时返回的表达式。如果省略此参数并且比较运算取值不为 TRUE,CASE 将返回 NULL 值。else_expression 和所有 result_expression 的数据类型必须相同,或者必须是隐性转换。
(2)CASE 搜索函数
CASE
WHEN Boolean_expression THEN
result_expression [...n ]
ELSE
else_expression
END
说明:when_expression 替换成 Boolean_expression。Boolean_expression 是任意有效的布尔表达式。
举例:
SELECT
CASE parent_id
WHEN 0 THEN
'00'
WHEN 1 THEN
'11'
ELSE
'OTHERS'
END AS parent_id_new ,
parent_id ,
type_id ,
type_name
FROM
tdb_goods_types
十一、别名设置
在査询数据时可为表和字段取別名,该别名代替表和字段的原名参与查询操作。
1.为表取别名
在查询操作时,假若表名很长使用起来就不太方便,此时可为表取一个別名,用该别名来代替表的名称。语法格式如下所示:
SELECT * FROM 表名 [AS] 表的别名 WHERE .... ;
将student改为stu查询整表:
select * from student as stu;
2.为字段取别名
在查询操作时,假若字段名很长使用起来就不太方便,此时可该字段取一个別名,用该别名来代替字段的名称。语法格式如下所示,as 可以省略
SELECT 字段名1 [AS] 别名1 , 字段名2 [AS] 别名2 , ...
FROM 表名 WHERE ... ;
将student中的name取别名为“姓名” 查询整表 MySQL命令:
select name as '姓名', id from student;
十二、表的关联关系
1.三种关联关系
在实际开发中数据表之间存在着各种关联关系,主要有以下三种关联关系。
(1)一对多 :数据表中最常见的一种关系。例如:员工与部门之间的关系,一个部门可以有多个员工;而一个员工不能属于多个部门只属于某个部门。在一对多的表关系 中,应将外键设置在多方,否则会造成数据的冗余。
(2)多对多 :数据表中常见的一种关系。例如:学生与老师之间的关系,一个学生可以有多个老师,一个老师也可以有多个学生。通常情况下,为了实现这种关系需要定义一张中间表(亦称为连接表),该表会存在两个外键分别参照老师表和学生表。
(3)一对一 :在开发过程中,一对一的关联关系在数据库中并不常见;因为以这种方式存储的信息通常会放在同一张表中。
2.一对多关系中的CRUD
先准备一些测试数据,代码如下:
DROP TABLE IF EXISTS student;
DROP TABLE IF EXISTS class;
-- 创建班级表
CREATE TABLE class(
cid int(4) NOT NULL PRIMARY KEY,
cname varchar(30)
);
-- 创建学生表
CREATE TABLE student(
sid int(8) NOT NULL PRIMARY KEY,
sname varchar(30),
classid int(8) NOT NULL
);
-- 为学生表添加外键约束
ALTER TABLE student
ADD CONSTRAINT fk_student_classid
FOREIGN KEY(classid) REFERENCES class(cid);
-- 向班级表插入数据
INSERT INTO class(cid,cname)VALUES(1,'Java');
INSERT INTO class(cid,cname)VALUES(2,'Python');
-- 向学生表插入数据
INSERT INTO student(sid,sname,classid)VALUES(1,'tome',1);
INSERT INTO student(sid,sname,classid)VALUES(2,'lucy',1);
INSERT INTO student(sid,sname,classid)VALUES(3,'lili',2);
INSERT INTO student(sid,sname,classid)VALUES(4,'domi',2);
(1)关联查询
查询Java班的所有学生 MySQL命令:
select * from student
where classid=(
select cid from class
where cname='Java'
);
(2)删除数据
请从班级表中删除Java班级,但注意:班级表和学生表之间存在关联关系;要删除Java班级,应该先删除学生表中与该班相关联的学生。否则学生表中的cid就会失去关联。
删除Java班的命令:
--先删除学生
delete from student
where classid=(
select cid from class where cname='Java'
);
--再删除班级
delete from class where cname='Java';
十三、多表连接查询
1.内连接查询
内连接(Inner Join)是一种最常见的连接查询。如果不加等值条件(ON),得到的就是笛卡尔积。
内连接使用比较运算符对两个表中的数据进行比较,并列出与连接条件匹配的数据行,组合成新的记录。也就是说在内连接查询中,只有满足条件的记录才能出现在查询结果中。其语法格式如下:
SELECT 字段1,字段2, ...
FROM 表1 [INNER] JOIN 表2
ON 表1.关系字段 = 表2.关系字段
INNER JOIN用于连接两个表,ON来指定连接条件。其中INNER可以省略。
准备数据,代码如下:
-- 若存在数据库mydb则删除
DROP DATABASE IF EXISTS mydb;
-- 创建数据库mydb
CREATE DATABASE mydb;
-- 选择数据库mydb
USE mydb;
-- 创建部门表
CREATE TABLE department(
did int (4) NOT NULL PRIMARY KEY,
dname varchar(20)
);
-- 创建员工表
CREATE TABLE employee (
eid int (4) NOT NULL PRIMARY KEY,
ename varchar (20),
eage int (2),
departmentid int (4) NOT NULL
);
-- 向部门表插入数据
INSERT INTO department VALUES(1001,'财务部');
INSERT INTO department VALUES(1002,'技术部');
INSERT INTO department VALUES(1003,'行政部');
INSERT INTO department VALUES(1004,'生活部');
-- 向员工表插入数据
INSERT INTO employee VALUES(1,'张三',19,1003);
INSERT INTO employee VALUES(2,'李四',18,1002);
INSERT INTO employee VALUES(3,'王五',20,1001);
INSERT INTO employee VALUES(4,'赵六',20,1004);
查询员工姓名及其所属部门名称:
select employee.ename,department.dname
from department inner join employee
on department.did = employee.departmentid;
2.外连接查询
内连接查询时,返回的结果只包含符合查询条件和连接条件的数据。但是,除了符合条件的数据,有时还需要在返回查询结果中包含左表、右表或两个表中的所有数据,此时我们就需要使用外连接查询。
外连接又分为左外连接和右外连接。其语法格式如下:
SELECT 字段1,字段2, ...
FROM 表1 LEFT/RIGHT JOIN 表2
ON 表1.关系字段=表2.关系字段
WHERE 条件
由此可见,外连接的语法格式和内连接非常相似,只不过使用的是LEFT JOIN、RIGHT JOIN关键字。在使用左(外)连接和右(外)连接查询时,查询结果是不一致的,具体如下:
1、LEFT [OUTER] JOIN 左外连接:返回包括左表中的所有记录和右表中符合连接条件的记录。
2、RIGHT [OUTER] JOIN 右外连接:返回包括右表中的所有记录和左表中符合连接条件的记录。
先准备数据,代码如下:
-- 若存在数据库mydb则删除
DROP DATABASE IF EXISTS mydb;
-- 创建数据库mydb
CREATE DATABASE mydb;
-- 选择数据库mydb
USE mydb;
-- 创建班级表
CREATE TABLE class(
cid int (4) NOT NULL PRIMARY KEY,
cname varchar(20)
);
-- 创建学生表
CREATE TABLE student (
sid int (4) NOT NULL PRIMARY KEY,
sname varchar (20),
sage int (2),
classid int (4) NOT NULL
);
-- 向班级表插入数据
INSERT INTO class VALUES(1001,'Java');
INSERT INTO class VALUES(1002,'C++');
INSERT INTO class VALUES(1003,'Python');
INSERT INTO class VALUES(1004,'PHP');
-- 向学生表插入数据
INSERT INTO student VALUES(1,'张三',20,1001);
INSERT INTO student VALUES(2,'李四',21,1002);
INSERT INTO student VALUES(3,'王五',24,1002);
INSERT INTO student VALUES(4,'赵六',23,1003);
INSERT INTO student VALUES(5,'Jack',22,1009);
准备这组数据有一定的特点,为的是让大家直观的看出左连接与右连接的不同之处
1、班级编号为1004的PHP班级没有学生
2、学号为5的学生王跃跃班级编号为1009,该班级编号并不在班级表中
3.1. 左连接查询
查询结果包括LEFT JOIN子句中指定的左表的所有记录,以及所有满足连接条件的记录。如果左表的某条记录在右表中不存在,则在右表对应地方显示为空。
查询每个班的班级ID、班级名称及该班的所有学生的名字:
select class.cid,class.cname,student.sname
from class left outer join student
on class.cid=student.classid;
结果分析:
1、分别找出Java班、C++班、Python班的学生
2、右表的王跃跃不满足查询条件,所以没有出现在查询结果中
3、虽然左表的PHP班没有学生,但是仍然显示了PHP的信息,且对应的学生名字为NULL。
3.2 右连接查询
右连接的结果包括RIGHT JOIN子句中指定的右表的所有记录,以及所有满足连接条件的记录。如果右表的某条记录在左表中没有匹配,则左表将返回空值。
查询每个班的班级ID、班级名称及该班的所有学生的名字 MySQL命令:
select class.cid,class.cname,student.sname
from class right outer join student
on class.cid=student.classid;
结果分析:
1、分别找出Java班、C++班、Python班的学生
2、左表的PHP班不满足查询条件,所以没有出现在查询结果中
3、虽然右表的 jack 没有对应班级,但是仍然显示王跃跃的信息,且它对应的班级以及班级编号均为NULL。
3.交叉连接查询(了解)
交叉连接返回的结果是:被连接的两个表中所有数据行的笛卡儿积。比如:集合A={a,b},集合B={0,1,2},则集合A和B的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。
所以,交叉连接也被称为笛卡尔连接,其语法格式如下:
SELECT * FROM 表1 CROSS JOIN 表2;
CROSS JOIN用于连接两个要查询的表,通过该语句可以查询两个表中所有的数据组合。由于这个交叉连接查询在实际运用中没有任何意义,所以只做为了解即可。
十四、子查询
子查询是指一个查询语句嵌套在另一个查询语句内部的查询,该查询语句可以嵌套在一个 SELECT、SELECT…WHERE、INSERT…INTO等语句中。
在执行查询时,首先会执行子查询中的语句,再将返回的结果作为外层查询的过滤条件。
在子査询中通常可以使用比较运算符和 IN、EXISTS、ANY、ALL等关键字。
1.带比较运算符的子查询
比较运算符前面我们提到过得,就是 >、<、=、>=、<=、!=等
查询张三同学所在班级的信息 MySQL命令:
select * from class
where cid=(
select classid from student
where sname='张三'
);
查询比张三同学所在班级编号还大的班级的信息 MySQL命令:
select * from class
where cid > (
select classid from student
where sname='张三'
);
2.带EXISTS关键字的子查询
EXISTS关键字后面的参数可以是任意一个子查询, 它不产生任何数据只返回TRUE或FALSE。当返回值为TRUE时外层查询才会执行。
判断如果王五同学在学生表中,则从班级表查询所有班级信息:
select * from class
where exists (
select * from student where sname='王五'
);
3.带ANY关键字的子查询
ANY关键字表示满足其中任意一个条件就返回一个结果作为外层查询条件。
查询比任一学生所属班级号还大的班级:
select * from class
where cid > any (
select classid from student
);
4.带ALL关键字的子查询
带ALL关键字的子査询返回的结果,需同时满足所有内层査询条件,才能作为外层查询条件。
查询比所有学生所属班级号还大的班级编号 :
select * from class
where cid > all (
select classid from student
);
总结
以分组group by 为界,where是分组前的筛选,having是分组后的筛选!
order by 与 limit 写在最后!
1.查询语句的书写顺序和执行顺序
select ===> from ===> where ===> group by ===> having ===> order by ===> limit
2.查询语句的执行顺序
from ===> where ===> group by ===> having ===> select ===> order by ===> limit