第06天 MySQL数据库
今日内容介绍
u MySQL单表查询
u SQL约束
u 多表操作
第1章 MySQL单表查询
1.1 SQL单表查询--排序
1.1.1 排序格式
通过order by语句,可以将查询出的结果进行排序。放置在select语句的最后。
格式:
SELECT * FROM 表名 ORDER BY 排序字段 ASC|DESC;
ASC 升序 (默认)
DESC 降序
#1.使用价格排序(降序)
SELECT * FROM product ORDER BY price DESC;
#2.在价格排序(降序)的基础上,以分类排序(降序)
SELECT * FROM product ORDER BY price DESC,category_id DESC;
#3.显示商品的价格(去重复),并排序(降序)
SELECT DISTINCT price FROM product ORDER BY price DESC;
1.1.2 案例练习一
#排序
#1.1.使用价格排序(降序)
SELECT * FROM product ORDER BY price DESC;
#1.2.在价格排序(降序)的基础上,以分类排序(降序)
SELECT * FROM product ORDER BY price DESC,category_id DESC;
#1.3.显示商品的价格(去重复),并排序(降序)
SELECT DISTINCT price FROM product ORDER BY price DESC;
SELECT DISTINCT price FROM product ORDER BY price ASC;
SELECT DISTINCT price FROM product ORDER BY price;
1.2 SQL单表查询--聚合
之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个单一的值;另外聚合函数会忽略空值。
今天我们学习如下五个聚合函数:
l count:统计指定列不为NULL的记录行数;
l sum:计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;
l max:计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;
l min:计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
l avg:计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;
1.2.1 案例练习二
#1 查询商品的总条数
SELECT COUNT(*) FROM product;
#2 查询价格大于200商品的总条数
SELECT COUNT(*) FROM product WHERE price > 200;
#3 查询分类为'c001'的所有商品的总和
SELECT SUM(price) FROM product WHERE category_id = 'c001';
#4 查询分类为'c002'所有商品的平均价格
SELECT AVG(price) FROM product WHERE category_id = 'c002';
#5 查询商品的最大价格和最小价格
SELECT MAX(price),MIN(price) FROM product;
1.3 SQL单表查询--分组
分组查询是指使用group by字句对查询信息进行分组。
l 格式:
SELECT 字段1,字段2… FROM 表名 GROUP BY分组字段 HAVING 分组条件;
分组操作中的having子语句,是用于在分组后对数据进行过滤的,作用类似于where条件。
l having与where的区别:
n having是在分组后对数据进行过滤.
where是在分组前对数据进行过滤
n having后面可以使用分组函数(统计函数)
where后面不可以使用分组函数。
1.3.1 案例练习三
#1 统计各个分类商品的个数
SELECT category_id ,COUNT(*) FROM product GROUP BY category_id ;
#2 统计各个分类商品的个数,且只显示个数大于1的信息
SELECT category_id ,COUNT(*) FROM product GROUP BY category_id HAVING COUNT(*) > 1;
1.4 数据库的备份与还原
1.4.1 SQL备份
选中数据库,右键 ”备份/导出” , 指定导出路径,保存成.sql文件即可。
1.4.2 SQL恢复
数据库列表区域右键“从SQL转储文件导入数据库”, 指定要执行的SQL文件,执行即可。
第2章 SQL约束
2.1 SQL约束--主键约束
PRIMARY KEY 约束唯一标识数据库表中的每条记录。
主键必须包含唯一的值。
主键列不能包含 NULL 值。
每个表都应该有一个主键,并且每个表只能有一个主键。
2.1.1 添加主键约束
l 方式一:创建表时,在字段描述处,声明指定字段为主键:
CREATE TABLE Persons
(
Id_P int PRIMARY KEY
,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
l 方式二:创建表时,在constraint约束区域,声明指定字段为主键:
n 格式:[constraint 名称] primary key (字段列表)
n 关键字constraint可以省略,如果需要为主键命名,constraint不能省略,主键名称一般没用。
n 字段列表需要使用小括号括住,如果有多字段需要使用逗号分隔。声明两个以上字段为主键,我们称为联合主键。
CREATE TABLE Persons
(
FirstName varchar(255),
LastName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT pk_PersonID PRIMARY KEY (FirstName,LastName)
)
或
CREATE TABLE Persons
(
FirstName varchar(255),
LastName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (FirstName,LastName)
)
l 方式三:创建表之后,通过修改表结构,声明指定字段为主键:
ALTER TABLE Persons ADD [CONSTRAINT
名称] PRIMARY KEY (字段列表)
CREATE TABLE Persons
(
FirstName varchar(255),
LastName varchar(255),
Address varchar(255),
City varchar(255)
)
ALTER TABLE Persons ADD PRIMARY KEY (FirstName,LastName)
2.1.2 删除主键约束
如需撤销 PRIMARY KEY 约束,请使用下面的 SQL:
ALTER TABLE Persons DROP PRIMARY KEY
2.2 SQL约束--自动增长列
2.2.1 自动增长
我们通常希望在每次插入新记录时,数据库自动生成字段的值。
我们可以在表中使用 auto-increment(自动增长列)关键字,自动增长列类型必须是整形,自动增长列必须为键(一般是主键)。
l 下列 SQL 语句把 "Persons" 表中的 "P_Id" 列定义为 auto-increment 主键
CREATE TABLE Persons
(
P_Id int PRIMARY KEY AUTO_INCREMENT,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
l 向persons添加数据时,可以不为P_Id字段设置值,也可以设置成null,数据库将自动维护主键值:
INSERT INTO Persons (FirstName,LastName) VALUES ('Bill','Gates')
INSERT INTO Persons (P_Id,FirstName,LastName) VALUES (NULL,'Bill','Gates')
l 面试:delete和truncate的区别
n Delete删除表中的数据,但不重置auto-increment记录数。
n Truncate删除表中的数据,auto-increment记录数将重置。Truncate其实先删除表然后再创建表。
l 扩展:默认地,AUTO_INCREMENT 的开始值是 1,如果希望修改起始值,请使用下列 SQL 语法:
ALTER TABLE Persons AUTO_INCREMENT=100
2.2.2 案例练习四
##自动增长列
CREATE TABLE ai01(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(50)
);
# 向表中插入数据
INSERT INTO ai01(NAME) VALUES('a');
INSERT INTO ai01(id,NAME) VALUES(NULL,'a');
## 自动增长列非法使用
CREATE TABLE ai02(
id VARCHAR(32) PRIMARY KEY AUTO_INCREMENT, #字段描述错误,类型不对
NAME VARCHAR(50)
);
CREATE TABLE ai03(
id INT AUTO_INCREMENT, #自动增长列必须是键(一般是主键)
NAME VARCHAR(50)
);
#扩展:设置自动增长列初始值,id默认值为1
CREATE TABLE ai04(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(50)
);
ALTER TABLE ai04 AUTO_INCREMENT = 100;
INSERT INTO ai04(NAME) VALUES('a');
#面试题 :delete 和 truncate 区别
## delete 删除表数据,但不重置自动增长列记录数。
##truncate 删除表数据,重置自动增长列的记录数。(先删除表,再创建表)
DELETE FROM ai01;
TRUNCATE TABLE ai01;
2.3 SQL约束--非空约束
NOT NULL 约束强制列不接受 NULL 值。
NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。
l 下面的 SQL 语句强制 "Id_P" 列和 "LastName" 列不接受 NULL 值:
CREATE TABLE Persons
(
Id_P int NOT NULL
,
LastName varchar(255) NOT NULL
,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
2.4 SQL约束--唯一约束
UNIQUE 约束唯一标识数据库表中的每条记录。
UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证。
PRIMARY KEY 拥有自动定义的 UNIQUE 约束。
请注意,每个表可以有多个 UNIQUE 约束,但是每个表只能有一个 PRIMARY KEY 约束。
2.4.1 添加唯一约束
与主键添加方式相同,共有3种,
l 方式1:创建表时,在字段描述处,声明唯一:
CREATE TABLE Persons
(
Id_P int UNIQUE
,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
l 方式2:创建表时,在约束区域,声明唯一:
CREATE TABLE Persons
(
Id_P int,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT
名称UNIQUE (Id_P)
)
l 方式3:创建表后,修改表结构,声明字段唯一:
ALTER TABLE Persons ADD [CONSTRAINT
名称] UNIQUE (Id_P)
2.4.2 删除唯一约束
l 如需撤销 UNIQUE 约束,请使用下面的 SQL:
ALTER TABLE Persons DROP INDEX
名称
如果添加唯一约束时,没有设置约束名称,默认是当前字段的字段名。
2.4.3 案例练习五
##唯一约束
CREATE TABLE un01(
id VARCHAR(32),
NAME VARCHAR(50)
);
ALTER TABLE un01 ADD CONSTRAINT u0001 UNIQUE (id);
#删除
ALTER TABLE un01 DROP INDEX u0001;
##如果没有设置约束名称,唯一约束名称默认是字段名称
CREATE TABLE un02(
id VARCHAR(32),
NAME VARCHAR(50)
);
ALTER TABLE un02 ADD UNIQUE (id);
#删除
ALTER TABLE un02 DROP INDEX id;
第3章 多表操作
3.1 表与表之间的关系
l 一对多关系:
n 常见实例:客户和订单,分类和商品,部门和员工.
n 一对多建表原则:在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键.
l 多对多关系:
n 常见实例:学生和课程、用户和角色
n 多对多关系建表原则:需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键.
l 一对一关系:(了解)
n 在实际的开发中应用不多.因为一对一可以创建成一张表.
n 两种建表原则:
u 外键唯一:主表的主键和从表的外键(唯一),形成主外键关系,外键唯一unique。
u 外键是主键:主表的主键和从表的主键,形成主外键关系。
3.2 外键约束
现在我们有两张表“分类表”和“商品表”,为了表明商品属于哪个分类,通常情况下,我们将在商品表上添加一列,用于存放分类cid的信息,此列称为:外键
此时“分类表category”称为:主表,“cid”我们称为主键。“商品表products”称为:从表,category_id称为外键。我们通过主表的主键和从表的外键来描述主外键关系,呈现就是一对多关系。
外键特点:
u 从表外键的值是对主表主键的引用。
u 从表外键类型,必须与主表主键类型一致。
l 声明外键约束
语法:alter table 从表 add [constraint] [外键名称] foreign key (从表外键字段名) references 主表 (主表的主键);
[外键名称] 用于删除外键约束的,一般建议“_fk”结尾
alter table 从表 drop foreign key 外键名称
l 使用外键目的:
n 保证数据完整性
3.3 一对多关系
3.3.1 一对多的表关系的分析与实现
3.3.1.1 分析
l category分类表,为一方,也就是主表,必须提供主键cid
l products商品表,为多方,也就是从表,必须提供外键category_id
3.3.1.2 实现:分类和商品
3.3.2 案例练习六
#创建数据库
CREATE DATABASE webdb_2;
#使用数据库
USE webdb_2;
####一对多关系
#1 创建主表:分类表
CREATE TABLE category(
cid VARCHAR(32) PRIMARY KEY,
cname VARCHAR(50)
);
#2 创建从表:商品表
CREATE TABLE products(
pid VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(50),
price INT,
category_id VARCHAR(32)
);
#3 将使用 主外键关系进行描述
ALTER TABLE products ADD CONSTRAINT products_fk FOREIGN KEY (category_id) REFERENCES category (cid);
3.3.3 一对多关系操作
3.3.4 案例练习七
#数据操作
#1 向分类表中插入数据
INSERT INTO category(cid,cname) VALUES('c001','服装');
#2 向商品表中插入数据,不含外键信息
INSERT INTO products(pid,NAME,price) VALUES('p001','KAMA服饰',100);
## 结论:外键数据默认可以为null
#3 向商品表中插入数据,含外键信息 (数据存在)
INSERT INTO products(pid,NAME,price,category_id) VALUES('p002','KAMA服饰2',100,'c001');
#4 向商品表中插入数据,含外键信息 (数据不存在)
INSERT INTO products(pid,NAME,price,category_id) VALUES('p003','KAMA服饰2',100,'c999');
## 结论:从表不能添加(或更新),主表不存在的数据。
#5 删除分类表的数据
#delete from products where category_id = 'c001'; #实际开发中解决方案
DELETE FROM category WHERE cid = 'c001';
## 结论:主表不能删除(或更新),从表中已经使用的数据。
#扩展:在一对多关系中,存在一种父子关系,主表又称为父表,从表又称为子表。
3.4 多对多关系
3.4.1 多对多表关系的分析和实现
l 商品和订单多对多关系,将拆分成两个一对多。
l products商品表,为其中一个一对多的主表,需要提供主键pid
l orders 订单表,为另一个一对多的主表,需要提供主键oid
l orderitem中间表,为另外添加的第三张表,需要提供两个外键oid和pid
3.4.2 案例练习八
#1 商品表[存在]
#2 订单表
CREATE TABLE orders(
oid VARCHAR(32) PRIMARY KEY,
totalprice INT #总价
);
#3 中间表
CREATE TABLE orderitem(
product_id VARCHAR(32), #对应商品表 products.pid
order_id VARCHAR(32) #对应订单表 orders.oid
);
#4 描述2次,主外键关系
#4.1 中间表 与 商品表 主外键关系
ALTER TABLE orderitem ADD CONSTRAINT orderitem_product_fk FOREIGN KEY (product_id) REFERENCES products (pid);
#4.2 中间表 与 订单表 主外键关系
ALTER TABLE orderitem ADD CONSTRAINT orderitem_order_fk FOREIGN KEY (order_id) REFERENCES orders (oid);
#5 扩展:中间表2个外键字段,一般形成联合主键(2个组合在一起唯一)[可选]
ALTER TABLE orderitem ADD CONSTRAINT PRIMARY KEY (product_id , order_id);
3.4.3 多对多表关系的操作
3.4.4 案例练习九
###操作
#1 向商品表插入数据
INSERT INTO products(pid,NAME,price) VALUES('p003','商品001',998);
#2 向订单表插入数据
INSERT INTO orders(oid,totalprice) VALUES('x001',100);
#3 向中间表插入数据(存在)
INSERT INTO orderitem(product_id,order_id) VALUES('p003','x001');
INSERT INTO orderitem(product_id,order_id) VALUES('p002','x001');
## 结论:多对多关系,如果两个主表建立联系,需要向中间表插入数据。
#4 删除中间表的数据
DELETE FROM orderitem WHERE product_id = 'p003' AND order_id = 'x001';
#5 向中间表插入数据(不存在) -- 运行异常
INSERT INTO orderitem(product_id,order_id) VALUES('p003','x002');
-- 注意:维护中间表时,数据必须存在
#6 删除订单表(主表)数据(被使用中) -- 运行异常
DELETE FROM orders WHERE oid = 'x001';
###一对多和多对多操作对比
#一对多维护关系时,操作从表的外键(一个字段)
#多对多维护关系时,操作整个中间表(一张表)