第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';

 

 

###一对多和多对多操作对比

#一对多维护关系时,操作从表的外键(一个字段)

#多对多维护关系时,操作整个中间表(一张表)