打开phpstudy中的MySQL和Nginx,Win+R快捷键输入cmd呼出命令窗口,输入mysql -uroot -p指令,输入密码进入指令模式。
1、DDL
1.1 数据库操作
使用DDL语句可以创建、查询、修改、删除数据库。
1.1.1 查询数据库
show databases;
show create database <数据库名>;
1.1.2 创建数据库
create database <数据库名>;
create database if not exists <数据库名>;
create database <数据库名> character set <目标字符集>;
1.1.3 修改数据库:修改数据库的字符集
alter database <数据库名> character set <目标字符集>;
1.1.4 删除数据库:删除数据库中所有数据表以及数据表中的数据
drop database <数据库名>;
drop database if exists <数据库名>;
1.2 数据表(关系)操作
数据表:即二维表格,由多行多列组成,表格中的每一列称为字段(属性),每一行称为元组。 使用DDL语句可以创建、查询、删除、修改数据表。 在对表关系进行操作前,需要指明当前数据表操作所在的数据库。
use <数据库名>;
1.2.1 创建数据表
create table <表名>(字段名1 类型1 约束1,字段名2 类型2 约束2,...字段名n 类型n 约束n);
1.2.2 查询数据表
show tables;
desc <表名>;
1.2.3 删除数据表
drop table <表名>;
drop table if exists <表名>;
1.2.4 修改数据表
alter table <原表名> rename to <目标表名>;
alter table <表名> character set <目标字符集>;
alter table <表名> add <字段名> <字段类型>;
alter table <表名> modify <目标字段名> <目标类型>;
alter table <表名> change <原字段名> <目标字段名> <目标类型>;
alter table <表名> drop <目标字段名>;
1.2.5 数据类型:数据表中列支持存放数据的类型
1.2.5.1 数值类型 MySQL有多种数据类型可存放数值,不同类型存放的范围或形式不同
类型 | 内存空间大小 | 范围 | 说明 |
---|
tinyint | 1byte | 有符号:-128~+127 无符号:0~+255 | 超小型整数 如年龄、身高 | smallint | 2byte(16bit) | 有符号:-32768~+32767 无符号:0~+65535 | 小型整数 | mediumint | 3byte | 有符号:-
2
23
2^{23}
223~+
2
23
2^{23}
223-1 无符号:0~+
2
24
2^{24}
224-1 | 中型整数 | int/integer | 4byte | 有符号:-
2
31
2^{31}
231~+
2
31
2^{31}
231-1 无符号:0~+
2
32
2^{32}
232-1 | 整数 常用 | bigint | 8byte | 有符号:-
2
63
2^{63}
263~+
2
63
2^{63}
263-1 无符号:0~+
2
64
2^{64}
264-1 | 大型整数 | float | 4byte | | 单精度 | double | 8byte | | 双精度 | decimal | | | decimal(m,n)必须 指定整数位m位 小数位n位 如decimal(2,3)表示最大数为99.999 |
1.2.5.2 字符类型:存储字符序列的类型
类型 | 序列长度范围 | 说明 |
---|
char(n) | 0~255byte | 定长字符串,最多255个字符 n表示规定此类型的长度 若不足n,则自动添加’\u0000’即空格 | varchar(n) | 0~65535byte | 变长字符串,最多65535个字符 n表示规定此类型最长长度 | tinyblob | 0~255byte | 存储二进制字符串 | blob | 0~65535byte | 存储二进制字符串 | mediumblob | 0~1677215byte | 存储二进制字符串 | longblob | 0~4294967295byte | 存储二进制字符串 | tinytext | 0~255byte | 文本数据 | tiny | 0~65535byte | 文本数据 | mediumtext | 0~1677215byte | 文本数据 | longtext | 0~4294967295byte | 文本数据 |
1.2.5.3 日期类型 MySQL数据库中可使用字符串类型来存储时间,但某些情况下需要基于时间段进行查询(如查询某个时间段内的数据)就不便于实现
类型 | 格式 | 说明 |
---|
date | year-month-day | 日期 只存储年月日 | time | hour:minute:second | 时间 只存储时分秒 | year | year | 年份 只存放年 | datetime | year-month-day hour:minute:second | 详细时间 | timestamp | yearmonthday hourminutesecond | 详细时间戳 |
1.2.6 字段约束
创建数据表时,指定对数据表的列的数据限制性要求。常见约束有非空约束(not null)、唯一约束(unique)、主键约束(primary key)、外键约束(foreign key) 1.2.6.1 非空约束:限制数据表中指定列的值不能为空 1.2.6.2 唯一约束:限制数据表中多条数据的值不能重复 1.2.6.3 主键约束:非空且唯一,主键可以是一列,也可是多个列的组合 ▲主键自动增长(auto_increment):一些情况下,数据表中的主键是根据添加的数据自动增长的,就可以设置主键自动增长属性。当向数据表中新增记录时,主键根据上条记录(包括已被删除的记录)的主键自增。 1.2.6.4 联合主键:将数据表中的多列组合一起设置为表的主键
primary key(字段名1,字段名2...);
1.2.6.5 外键约束
1.2.7 数据表相关操作示例
1.2.7.1 创建学生信息表
USE test;
CREATE TABLE stu_info(
id INT PRIMARY KEY,
name VARCHAR(10) NOT NULL,
sex VARCHAR(10) NOT NULL,
age TINYINT NOT NULL,
birthday DATE NOT NULL,
telephone VARCHAR(15) UNIQUE,
address VARCHAR(20)
);
ALTER TABLE stu_info RENAME TO student_information;
ALTER TABLE student_information ADD remark VARCHAR(100);
ALTER TABLE student_information MODIFY age INT;
ALTER TABLE student_information DROP remark;
1.2.7.2 创建图书管理表
USE test;
CREATE TABLE books_table(
books_id INT PRIMARY KEY AUTO_INCREMENT,
books_name VARCHAR(30) NOT NULL,
books_author VARCHAR(25) NOT NULL,
books_remark VARCHAR(100)
);
通过phpMyAdmin工具在表中插入示例中的数据
INSERT INTO `books_table` (`books_id`, `books_name`, `books_author`, `books_remark`) VALUES ('1', 'Java', 'Kathy Sierra', NULL), (NULL, 'Python', 'Mark Lutz', NULL), (NULL, 'C++', 'Stephen Prata', NULL);
SELECT * FROM `books_table`;
删除最后一行数据,再在尾部增加另外一行数据
DELETE FROM `books_table` WHERE `books_table`.`books_id` = 3;
INSERT INTO `books_table` (`books_id`, `books_name`, `books_author`, `books_remark`) VALUES (NULL, 'C', 'Martin Richards', NULL);
2、DML
2.1 添加数据
insert into <表名> (字段名1,字段名2,...,字段名n) values (值1,值2,...,值n);
insert into <表名> values (值1,值2,...,值n);
2.2 删除数据
delete from <表名> [where <条件>];
2.3 修改数据
update <表名> set <字段名1>=<值1>,<字段名2>=<值2>... [where <条件>];
2.4 DML示例:创建班级学生信息表
USE test;
CREATE TABLE class_info(
stu_id INT PRIMARY KEY AUTO_INCREMENT,
stu_name VARCHAR(30) NOT NULL,
stu_gender VARCHAR(10) NOT NULL,
stu_nativeplace VARCHAR(20),
stu_grade VARCHAR(5) NOT NULL
);
INSERT INTO class_info (stu_id,stu_name,stu_gender,stu_grade) VALUES (1001,'Mike','male','A');
INSERT INTO class_info (stu_name,stu_gender,stu_nativeplace,stu_grade) VALUES ('Tom','male','Shanghai','B');
INSERT INTO class_info (stu_name,stu_gender,stu_nativeplace,stu_grade) VALUES ('Jenny','female','Hongkong','A');
INSERT INTO class_info (stu_name,stu_gender,stu_grade) VALUES ('Mary','female','B');
INSERT INTO class_info (stu_name,stu_gender,stu_nativeplace,stu_grade) VALUES ('Jim','male','Beijing','A');
DELETE FROM class_info WHERE stu_id=1005;
UPDATE class_info SET stu_nativeplace='Chengdu',stu_grade='A' WHERE stu_id=1004;
SELECT * FROM class_info;
UPDATE class_info SET stu_nativeplace='Beijing';
SELECT * FROM class_info;
3、DQL
3.1 查询基础语法
select <字段名1,字段名2...> from <表名> [where <条件>];
select * from <表名> [where <条件>];
3.2 where子句:用于筛选满足特定条件的数据
[语句] where <条件>;
说明:在where子句中,若多条件查询,需要通过逻辑运算符(and or not)进行连接多个条件;若区间查询,可使用between a and b(等价于区间[a,b])语句进行查询。
3.3 like子句
在where子句的条件中,可使用like关键字实现模糊查询。
SELECT * FROM stus WHERE name LIKE '%o%';
符号 | 含义 | 示例 |
---|
% | 任意数量(包括0)的字符 | %o%表示字符串中包含字母o | _ | 任意一个字符 | _o%表示字符串中o的处于第二个字母处 __o%表示字符串中o的处于第三个字母处 |
3.4 DQL示例及查询结果处理
在上例中班级学生信息表中添加stu_birth字段以存储学生的出生年份。
ALTER TABLE class_info ADD stu_birth INT;
UPDATE class_info SET stu_birth=2005 WHERE stu_id=1001;
UPDATE class_info SET stu_birth=2006 WHERE stu_id=1002;
UPDATE class_info SET stu_birth=2004 WHERE stu_id=1003;
UPDATE class_info SET stu_birth=2003 WHERE stu_id=1005;
SELECT stu_name,2022-stu_birth AS stu_age FROM class_info;
SELECT DISTINCT stu_nativeplace FROM class_info;
SELECT * FROM class_info WHERE stu_name LIKE '%y';
SELECT * FROM class_info WHERE stu_name LIKE '%e%';
3.5 order by排序
将查询到满足条件的记录按照指定的列的值升序或降序排列。
[语句] [where <条件> order by <字段名1> [asc],...,<字段名n> [asc]];
[语句] [where <条件> order by <字段名1> desc,...,<字段名n> desc];
3.6 聚合函数
SQL中提供了一些可以对查询的记录的列进行计算的函数。常见的聚合函数有:count、max、min、sum、avg等。
select <函数名>(字段名) from <表名> [where <条件>];
函数 | 含义 |
---|
count | 统计函数 统计满足条件的元组的个数 | max | 最大值函数 满足条件指定列中的最大值 | min | 最小值函数 满足条件指定列中的最小值 | sum | 求和函数 满足条件指定列值的总和 | avg | 平均值函数 满足条件指定列值的平均值 |
3.7 其它函数:日期函数、字符串函数
函数 | 应用 |
---|
日期函数 | 当向日期类型添加数据时 可通过形如YYYY-MM-DD hh:mm:ss字符串类型赋值 获取当前系统详细时间使用now()或sysdate()函数 也可通过select now()或select sysdate()获取当前详细时间 curtime()获取当前系统时间;curdate()获取当前系统日期 | 字符串函数 | concat(多个字符串英文逗号隔开)将多个字符串拼接为一个字符串 upper(字段名)将字段名对应列大写 lower(字段名)将字段名对应列小写 substring(字段名,a,b)从下标a开始截取b个字段名对应列 注意SQL中字符串下标从1开始 |
3.8 分组查询
分组:将数据表中的记录按照指定的列进行分组。
select [<字段名1>...<字段名n>],[<聚合函数>] from <表名> [where <条件>] group by <目标分组字段>;
说明:select后使用*显示对查询结果进行分组后每组的第一条记录。其后通常使用字段名和聚合函数对分组后的数据进行相关操作。 ▲针对分组查询出的结果使用having关键字限制筛选
select [<字段名1>...<字段名n>],[<聚合函数>] from <表名> [where <条件>] group by <目标分组字段> having <条件>;
where条件和having条件的区别:先根据where条件从数据库查询记录后分组,分组后根据having条件对查询结果进行筛选。即where条件是针对原数据表进行筛选,having条件是针对分组后查询出数据表进行二次筛选,having关键字必与group by关键字同时出现。
3.9 分页查询
当数据表中的记录比较多的时候,若一次性全部查询出来显示给用户,用户的可读性/体验感不太完美,可将数据分页进行展示。
[语句] limit a,b;
页码 pageNum
总记录数 count
每页显示记录数 pageSize
总页数 pageCount=count%pageSize==0?count/pageSize:count/pageSize+1
[语句] limit (pageNum-1)*pageSize,pageSize;
4、多表联合
4.1 关联关系
MySQL是关系型数据库,不仅可存储数据,还可维护数据之间的关系。通过在数据表中添加字段建立外键约束。数据之间的关联关系分为四种:一对一关联、一对多关联、多对一关联、多对多关联。
4.1.1 一对一关联
生活中常常有一对一的关系实例,如人和身份证的关系,一个人只有一个身份证,一个身份证只对应一个人;某平台的用户和用户详情,一个用户只有一个详情,一个详情只对应一个用户。 ▲建立一对一关联的方法 方法1:主键关联:两张表中分别设置主键,根据主键的性质,每张表中数据的主键属性唯一,表间形成了唯一对应唯一的关联。即两张表中主键相同的数据为相互关联的数据。 方法2:唯一外键:在任意一张表中添加一个外键约束字段与另一张表主键关联,并且外键约束字段添加唯一unique约束以达到一对一的关联。
4.1.2 一对多、多对一关联
生活中常常有一对多/多对一的关系实例,如班级与学生的关系,一个班级对应多个学生,相反,多个学生对应一个班级。 ▲建立一对多/多对一关联的方法:在“多”的一端所对应的表中添加外键与“一”的一端所对应的表的主键进行关联,从而建立数据间一对多/多对一的关联。
4.1.3 多对多关联
生活中常常有多对多的关系实例,如学生与选课的关系,多个学生可以选择多门课,多门课也可由多名学生选择。 ▲建立多对多关联的方法:另外创建一张关系表来维护多对多关联。在关系表中定义两个外键,分别与两个表的主键进行关联。
4.2 外键约束
外键约束是将一张表添加外键约束与另一张表的主键(唯一)进行关联后,这个外键约束的字段添加的数据必须在关联的主键字段中存在。即外键约束的字段的域是关联的主键字段的域的子集。 示例:学生与班级之间的关系表(学生表中添加外键与班级表的主键进行关联)
CREATE DATABASE db01;
USE db01;
CREATE TABLE class_info(
class_id INT PRIMARY KEY AUTO_INCREMENT,
class_name VARCHAR(30) NOT NULL,
class_remark VARCHAR(50)
);
constraint <外键关联逻辑名> foreign key(<当前表的外键>) references <被关联表名>(<被关联表名主键>);
CREATE TABLE stu_info(
stu_id INT PRIMARY KEY,
stu_name VARCHAR(20) NOT NULL,
stu_gender VARCHAR(10) NOT NULL,
stu_age INT NOT NULL,
cid INT,
CONSTRAINT fk_stu_class FOREIGN KEY(cid) REFERENCES class_info(class_id)
);
INSERT INTO class_info (class_name) VALUES ('finance 1');
INSERT INTO class_info (class_name) VALUES ('finance 2');
INSERT INTO class_info (class_name) VALUES ('finance 3');
INSERT INTO stu_info (stu_id,stu_name,stu_gender,stu_age,cid) VALUES (1001,'zhangsan','male',20,2);
INSERT INTO stu_info (stu_id,stu_name,stu_gender,stu_age,cid) VALUES (1002,'lisi','female',21,3);
INSERT INTO stu_info (stu_id,stu_name,stu_gender,stu_age,cid) VALUES (1003,'wangwu','male',20,1);
INSERT INTO stu_info (stu_id,stu_name,stu_gender,stu_age,cid) VALUES (1004,'zhaoliu','male',19,1);
INSERT INTO stu_info (stu_id,stu_name,stu_gender,stu_age,cid) VALUES (1005,'chenqi','female',22,3);
4.3 连接查询
MySQL中可以使用join关键字实现多表的联合查询,即连接查询。按功能不同分为三个操作:内连接inner join、左连接left join、右连接right join。 内连接:两张表的笛卡尔积。
[语句] <表名1> inner join <表名2> [where <条件>];
[语句] <表名1> inner join <表名2> [on <条件>] [where <条件>];
左连接:展示左表中所有数据,若在右表中存在与左表记录满足连接条件的数据,则连接;否则展示为NULL。
[语句] <左表名> left join <右表名> on <条件> [where <条件>];
右连接:展示右表中所有数据,若在左表中存在与右表记录满足连接条件的数据,则连接;否则展示为NULL。
[语句] <左表名> right join <右表名> on <条件> [where <条件>];
5、练习
5.1 关系代数与SQL语句的转换
★视频:https://www.bilibili.com/video/BV1Au411R7oG?spm_id_from=333.999.0.0 有两个关系S(A,B,C,D)和T(C,D,E,F),写出与下列查询等价的SQL表达式? (1)σ
A
=
10
_{A=10}
A=10?(S)
SELECT * FROM S WHERE A=10;
(2)
Π
A
,
B
Π_{A,B}
ΠA,B?(S)
SELECT A,B FROM S;
(3)
S
?
T
A
<
E
S?T_{A<E}
S?TA<E?
SELECT * FROM S INNER JOIN T ON A<E;
(4)
S
?
T
S?T
S?T
SELECT A,B,S.C,S.D,E,F FROM S INNER JOIN T ON S.C=T.C AND S.D=T.D;
(5)
S
?
T
S
.
C
=
T
.
C
S?T_{S.C=T.C}
S?TS.C=T.C?
SELECT * FROM S INNER JOIN T ON S.C=T.C;
(6)
Π
C
,
D
Π_{C,D}
ΠC,D?(S)×T
SELECT S.C,S.D,T.* FROM S INNER JOIN T;
(7)S?T
SELECT A,B,S.C,S.D,E,F FROM S LEFT JOIN T ON S.C=T.C AND S.D=T.D;
(8)S?T
SELECT A,B,T.C,T.D,E,F FROM S RIGHT JOIN T ON S.C=T.C AND S.D=T.D;
5.2 DQL示例
★视频:https://www.bilibili.com/video/BV16r4y167Jf?spm_id_from=333.999.0.0 建立一个学生系统表(Student_System),存在字段id、name、gender、chinese_mark、math_mark、english_mark、last_logintime、tel。
CREATE TABLE student_system(
ID INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20) NOT NULL,
GENDER VARCHAR(10) NOT NULL,
CHINESE_MARK INT,
MATH_MARK INT,
ENGLISH_MARK INT,
LAST_LOGINTIME DATETIME,
TEL VARCHAR(20)
);
INSERT INTO student_system(ID,NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK,TEL) VALUES ('Carl','male',87,92,89,'3587325');
INSERT INTO student_system (NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK,LAST_LOGINTIME) VALUES ('Barry','male',90,94,90,now());
INSERT INTO student_system (NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK,LAST_LOGINTIME) VALUES ('Alice','female',95,92,92,'2022-01-31 09:00:00');
INSERT INTO student_system (NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK,TEL) VALUES ('Jack','male',89,89,91,'4412578');
INSERT INTO student_system (NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK,TEL) VALUES ('Jim','male',92,90,91,'2569493');
INSERT INTO student_system (NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK) VALUES ('Anne','female',89,85,87);
INSERT INTO student_system (NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK) VALUES ('Paul','male',85,87,89);
INSERT INTO student_system (NAME,GENDER,CHINESE_MARK,MATH_MARK,ENGLISH_MARK) VALUES ('Tom','male',90,95,88);
SELECT ID,NAME,CHINESE_MARK FROM student_system ORDER BY CHINESE_MARK DESC;
SELECT * FROM student_system ORDER BY CHINESE_MARK DESC,MATH_MARK DESC,ENGLISH_MARK DESC;
SELECT CONCAT(NAME,'-',GENDER) FROM student_system;
SELECT SUBSTRING(TEL,2,4) FROM student_system;
SELECT CHINESE_MARK,COUNT(ID) FROM student_system GROUP BY CHINESE_MARK;
SELECT MATH_MARK,COUNT(ID) FROM student_system WHERE CHINESE_MARK>=90 GROUP BY MATH_MARK HAVING MATH_MARK>90;
SELECT * FROM student_system LIMIT 0,4;
5.3 多表联合查询
★视频:https://www.bilibili.com/video/BV1Qu41197ht?spm_id_from=333.999.0.0 设有一个SPJ数据库,包括S、P、J、SPJ共4个关系模式。 S(SNO,SNAME,STATUS,CITY) P(PNO,PNAME,COLOR,WEIGHT) J(JNO,JNAME,CITY) SPJ(SNO,PNO,JNO,QTY) 其中S是供应商表,由供应商代码(SNO)、供应商姓名(SNAME)、供应商状态(STATUS)、供应商所在城市(CITY)构成;P是零件表,由零件代码(PNO)、零件名(PNAME)、颜色(COLOR)、重量(WEIGHT)构成;J是工程项目表,由工程项目代码(JNO)、工程项目名(JNAME)、工程项目所在城市(CITY)构成;SPJ是供应情况表,由供应商代码(SNO)、零件代码(PNO)、工程项目代码(JNO)、供应数量(QTY)构成。其中供应数量QTY表示某供应商供应某种零件给某工程项目的数量为QTY。
CREATE TABLE S(
SNO VARCHAR(5),
SNAME VARCHAR(100),
STATUS INT,
CITY VARCHAR(100)
);
CREATE TABLE P(
PNO VARCHAR(5),
PNAME VARCHAR(100),
COLOR VARCHAR(100),
WEIGHT INT
);
CREATE TABLE J(
JNO VARCHAR(5),
JNAME VARCHAR(100),
CITY VARCHAR(100)
);
CREATE TABLE SPJ(
SNO VARCHAR(5),
PNO VARCHAR(5),
JNO VARCHAR(5),
QTY INT
);
(1)找出所有供应商的姓名和所在城市
SELECT SNAME,CITY FROM S;
(2)找出所有零件的名称、颜色、重量
SELECT PNAME,COLOR,WEIGHT FROM P;
(3)找出使用供应商S1所供应零件的工程号码
SELECT JNO FROM SPJ WHERE SNO='S1';
(4)找出工程项目J2使用的各种零件的名称及其数量
SELECT PNAME,QTY FROM SPJ INNER JOIN P ON SPJ.JNO='J2' AND SPJ.PNO=P.PNO;
(5)找出上海厂商供应的所有零件号码
SELECT DISTINCT PNO FROM S INNER JOIN SPJ ON S.CITY='ShangHai' AND S.SNO=SPJ.SNO;
(6)找出使用上海产的零件的工程名称
SELECT DISTINCT JNAME FROM S INNER JOIN SPJ INNER JOIN J ON S.CITY='ShangHai' AND S.SNO=SPJ.SNO AND SPJ.JNO=J.JNO;
(7)把全部红色零件的颜色改成蓝色
UPDATE P SET COLOR='blue' WHERE COLOR='red';
(8)由S5供给J4的零件P6改为由S3供应。
UPDATE SPJ SET SNO='S3' WHERE SNO='S5' AND PNO='P6' AND JNO='J4';
(9)从供应商关系中删除供应商号是S2的记录,并从供应情况关系中删除相应的记录。
DELETE FROM S WHERE SNO='S2';
DELETE FROM SPJ WHERE SNO='S2';
(10)请将(S2,J6,P4,200)插入供应情况关系。
INSERT INTO SPJ (SNO,JNO,PNO,QTY) VALUES ('S2','J6','P4',200);
|