py-02-DATABASE


目录:

01: 服务器概述、数据库服务器、创建数据库、创建数据表

02: 基础查询、增删改操作、复杂查询、关联查询

03: 常用函数、分页、触发器

04: 视图、存储过程、客户端工具SQLyog

05: 创建京淘电商中的所有数据库表之用户表和商品表

06: 综合项目实战

07: 创建京淘电商中的所有数据库表之购物车表和订单表

08:Mysql思维导图


01: 服务器概述、数据库服务器、创建数据库、创建数据表

1   数据库

存储数据的仓库

l  关系型数据库

   Oracle、Mysql、Sql Server、DB2、Sybase、Sqlite....

  

l  NO-SQL

   键值对数据库,redis、mongo db

l  混合数据库

2   Mysql

开源、免费数据库

2008年,Mysql创始人,以10亿美金把Mysql卖给Sun公司,一年后,Oracle收购了Sun公司

Oracle不重视Mysql的开发,开源社区缩小到指定的几家大公司,而且推出收费版Mysql

开源社区认为Mysql存在闭源风险,开源社区已经不支持Mysql

Mysql创始人在Mysql源码基础上,新开了一个分支:MariaDB,开源社区转向支持MariaDB

阿里也在向MariaDB贡献代码,17年10月,阿里给MariaDB投资3000万

3   Mysql安装

Mysql

   到官网下载免费的社区版

MariaDB

  

Linux安装:

   红帽子系列,yum

   Ubuntu系列,apt

4   Mysql客户端工具

mysql提供的命令行客户端: mysql

窗口客户端:

     Navicat

     Sql Yog 

     Mysql Front

     Workbench

    

4.1    用命令行客户端连接服务器

mysql -uroot -p -hxx.xxx.xx.xxx -P3306

-u  指定用户名

-p  使用密码登录

-h  指定连接的服务器ip

-P  指定连接的端口号

win+r 输入 cmd

cd C:\Program Files\MariaDB 5.5\bin

mysql -uroot -p   连接本机

输入密码

4.2    配置环境变量

配置PATH变量,在其中添加mysql的bin目录路径

5   mysql客户端的基本命令

5.1    查看数据库列表

mysql服务器上可以有多个数据存储区仓库,不同的库中可以分门别类存放不同的数据

show databases;
show schemas;

系统数据库:

INFORMATION_SCHEMA

MySQL

performance_schema

5.2    切换数据库

use test;

use mysql;

5.3    查看数据表列表

数据库中的数据,是存放在一张一张的二维表中

show tables;

5.4    查看表结构

一张表由多列(字段)组成,可以查看一张表有哪些列,列名是什么,列存储什么类型数据....

desc user;

查询表中的数据

select * from user\G

\G 纵向显示每行结果

5.5    退出mysql客户端

quit

\q

6   远程连接mysql服务器

mysql用户标识是用“ip+用户名”来标识用户

添加允许远程连接的用户,两步:

1.  新建用户:

'root'@'xx.xxx.xx.xxx'

'root'@'xx.xxx.xx.%'

'root'@'%'

create user 'abc'@'localhost'
identified by '123456'
       
create user 'abc'@'192.168.0.68'
identified by ''
       
create user 'abc'@'192.168.0.%'
identified by ''
       
 create user 'abc'@'%'
identified by ''

2.  为用户分配权限

grant select,insert,update,delete    
on test.* to 'abc'@'%'
       
grant create,alter,drop
on db1.* to 'abc'@'localhost'

grant all privileges
on *.* to 'root'@'%'
   
grant select,insert
on db1.t1 to 'abc'@'%'

grant select(id, name)
on db1.t1   to 'abc'@'%

允许远程登录的root用户

创建当前网段中访问的root
create user 'root'@'192.168.26.%'
identified by 'root';


为用户分配权限
grant all privileges
on *.* to 'root'@'192.168.26.%';


新开客户端,连接远程服务器
mysql -uroot -p -hxx.xxx.xxx.xx -P3306

7   中文问题

常用的中文字符编码:

   iso-8859-1

   latin-1

      欧美字符集

      都是单字节字符

   GBK

      国标

      默认是拼音排序

      英文使用单字节

      中文使用双字节

   UTF-8

      统一码Unicode的传输格式

      默认是笔画顺序

      英文是单字节

      中文是三个字节

在客户端,需要告诉服务器,客户端使用的是什么字符编码

服务器知道客户端是什么编码后,才能做正确的编码转换

告诉服务器,客户端使用什么编码

set names gbk;

8   数据库管理

8.1    创建数据库

create database 库名;

create database 库名

charset 字符编码;

创建数据库db1

create database db1
charset utf8;

show databases;

8.2    查看数据库

show databases;

查看建库代码

show create database db1\G

8.3    修改数据库

数据库只能修改它的默认字符集

alter database db1 charset gbk;

show create database db1\G

8.4    删除数据库

删除数据库会删除库中保存的所有数据

drop database if exists db1;

show databases;

9   数据表管理

9.1    创建表

create table 表名(

   字段1  数据类型,

   字段2  数据类型,

   字段3  数据类型

) engine=innodb或myisam charset=utf8;

创建商品表 item

--  创建db1库
create database db1 charset utf8;
--  进入db1库
use  db1;
--  创建item表
create table item(
id     int,
name   varchar(100)
)engine=innodb charset=utf8;
--  显示数据表列表
show tables;

9.2    查看表

show tables;

desc item;  -- describe

show create table item\G

9.3    修改表

9.3.1  改表名

rename table 原名 to 新名;

rename table item  to  tb_item;

show tables;

9.3.2  改表的属性

改存储引擎,改字符编码

alter table tb_item

engine=引擎 charset=编码;

alter table tb_item
engine=myisam  charset=gbk;

show create table tb_item\G

9.3.3  添加字段

位置设置:

      first 第一个

      after 指定字段之后

alter table tb_item

add 字段 类型 位置

alter table tb_item

add(

   字段1  数据类型,

   字段2  数据类型,

   字段3  数据类型

);

在tb_item表添加字段

alter table tb_item
add number int after id;

desc tb_item;

alter table tb_item
add (
   price decimal(8,2),
   description text
);


desc tb_item;

9.3.4  修改字段名

alter table tb_item
change name  title varchar(100);

desc tb_item;

9.3.5  修改字段类型

alter table tb_item
modify id bigint;

desc tb_item;

9.3.6  调整字段顺序

使用 first 和 after 设置字段位置

alter table tb_item
modify  number int after price;

desc tb_item;

9.3.7  删除字段

会删除字段中的数据,不可恢复

alter table tb_item
drop price;

desc tb_item;

9.4    删除表

会删除表中的数据,不可恢复

drop table if exists tb_item;

show  tables;

10     数据的增删改查

10.1  插入数据

drop table if exists tb_item;
 
create table tb_item(
   id     int,
   name   varchar(100),
   price  decimal(8,2)
) engine=innodb charset=utf8;
 
desc tb_item;
 
--  告诉服务器,客户端使用的是什么编码
set names gbk;
 
--  向表中插入数据
insert into tb_item values
(52, '苹果x', 8999.99),
(345, '华为P10', 4899.99),
(63, 'vivo', 7399.99);

10.2  查询数据

select * from tb_item;

10.3  修改数据

update tb_item
set name='荣耀v10', price=3999.99
where id=345;

select * from tb_item;

10.4  删除数据

delete from tb_item
where id=63;
 
select * from tb_item;

11     存储引擎

mysql 支持多种数据存储引擎,不同引擎存储数据的方式不同,支持的数据库功能不同

innodb(默认)

n  支持事务

n  支持外键

n  行级锁

n  磁盘文件:

u  tb_item.frm 表结构文件

u  tb_item.ibd 保存数据和索引数据

myisam

n  不支持事务和外键,数据访问效率更高

n  表级锁

n  查询多,修改少时,可以使用myisam

n  磁盘文件:

u  tb_item.frm 表结构文件

u  tb_item.MYD 保存数据

u  tb_item.MYI 保存索引数据

  

memory

   内存表

12     数据类型

12.1  数字类型

修饰符:

   unsigned 无符号,只有正数

   zerofill 用0填充

             int(5)

查询显示数据时,

不足5位显示5位,

超过5位没有影响

tinyint

1字节

smallint

2字节

int

4字节

bigint

8字节

float

4字节

double

8字节

decimal(m,n)

定点数,

(8,2)  m+2个字节

(3,3)  n+2 个字节

12.2  字符串类型

char(长度)

定长字符串,超出长度,可能出错或截断,长度不足会补空格;

最大长度是255个字符,

字节量:

GBK: 长度*2

UTF8: 长度*3

varchar(长度)

变长字符串,最大65535

如果指定的长度是<=255,

会额外添加一个字节表示数据长度

如果指定长度>255,需要两个额外字节表示数据长度

一般使用varchar来存储255内的数据

text

65535个字符

12.3  日期类型

datetime

年月日时分秒

date

年月日

time

时分秒

timestamp

时间戳,年月日时分秒,

时间范围最大到 2038年

修改数据时,表中的第一个timestamp字段,会自动更新为系统当前时间

不能存空值,存入空值时,自动填系统时间

13     练习

13.1  创建商品表 tb_item

--  新建数据库 jtdb
drop database if exists jtdb;
 
create database jtdb
charset utf8;
 
use  jtdb;
 
--  新建 tb_item 商品表
drop table if exists tb_item;
 
create table tb_item(
   id bigint comment '商品编号',
   cid bigint comment '所属叶子类目',
   brand varchar(50) comment '品牌',
   model varchar(50) comment '型号',
   title varchar(100) comment '标题名称',
   sell_point varchar(500) comment '卖点',
   price bigint comment '价格,单位是分',
   num int comment '库存数量',
   barcode varchar(30) comment '条码',
   image varchar(500) comment '图片路径',
   status tinyint comment '状态1正常2下架3删除',
   created datetime comment '添加数据时间',
   updated datetime comment '修改数据时间'
) engine=innodb charset=utf8;
 
 
show create table tb_item\G

14     作业

4.2.1 商品分类表(tb_item_cat)

id name parent_id is_parent sort_order
1  女装 0 1 2
2 电脑 0 1 3
3 手机 0 1 1
4 上衣 1 1 2
5 女裤 1   1
6 台式机 2   1
7 笔记本 2   2
8 联想 6 0 1
9 戴尔 6 0 2
10 联想 7 0  

表管理语法,自己重复练习


02: 基础查询、增删改操作、复杂查询、关联查询

1   数据表的字节量(了解)

mysql规定,一张表所有字段的字节量之和,不能超过 65535

l  如果表中存在允许 null (空)值的字段,这张表需要一个额外字节来表示空值

l  varchar <=255个字节,需要一个额外字节来表示长度,如果>255字节,需要两个额外字节来表示长度

l  text只占用表的10个字节量

表 65535 字节量限制测试

use db1;
set names gbk;
 
 
drop table if exists tb1;
 
--  1个字节表示null
create table tb1(
   a int,  --  4字节
   b double,  --  8字节
   c varchar(65510)  --  65510+2
   --  , d tinyint
   , e text  --  占表的10字节
)charset=latin1;

2   约束

对字段的取值进行约束、限制

l  主键

l  外键

l  非空

l  唯一

l  检查(mysql不支持)

l  默认值

2.1    主键

一行数据的唯一标识

主键字段

n  不重复

n  非空

n  自动添加索引

主键应该尽量使用非业务数据,业务数据可能会改变,应该使用与业务无关的无意义数据做为主键,常见的有自增整数,uuid随机字符串

id(pk)

学号

姓名

性别

1

10000234

xxx

3

5

6

7

     

id(pk)

身份证

姓名

性别

生日

a765c857e86h8a446

134234

xxx

c875a65985f069875

12534535

xxx

手机号(pk)

姓名

3245135

xxx

32452345

xxx

2.1.1  创建主键

l  建表时添加主键

create table tb1(
   id int primary key,
   ...
);

create table tb1(
   id int,
   ...,
   primary key(id)
);

l  修改表时添加主键

alter table tb1
add primary key(字段);

l  双主键(尽量不用)

primary key(字段1,字段2)

添加主键

drop table if exists xuesheng;
 
--  创建学生表
create table xuesheng(
   id int primary key,
   stu_id int,
   name varchar(20)
)engine=innodb charset=utf8;
 
insert into xuesheng values
(754, 2014196192, '张三');
-- Duplicate entry '754' for key 'PRIMARY'
insert into xuesheng values
(754, 2014196193, '李四');
--  Column 'id' cannot be null
insert into xuesheng values
(null, 2014196194, '王五');
 

2.1.2  查看主键

desc xuesheng;

show create table xuesheng\G

2.1.3  删除主键

alter table xuesheng
drop primary key;

desc xuesheng;
show create table xuesheng\G

2.1.4  自增主键

mysql中,主键可以设置自动增加,自增主键不需要手动插入数据,会自动产生值

也可以手动插入一个值

如果向自增主键插入 null 值,不会出错,而是自动产生自增值插进去

2.1.4.1        添加自增主键

create table tb1(
   id int primary key auto_increment,
   ...
);
 
create table tb1(
   id int auto_increment,
   ...,
   primary key(id)
);

l  修改表时,添加自增主键:

1)  添加主键约束

alter table xuesheng
add primary key(id);

2)  在主键上设置自增

alter table xuesheng
modify id int auto_increment;

2.1.4.2        查看自增主键

show create table xuesheng\G

测试自增主键

insert into xuesheng values
(null, 123, 'a');
 
select * from xuesheng;
 
insert into xuesheng values
(1, 124, 'b');
 
show create table xuesheng\G
 
insert into xuesheng values
(10000, 125, 'c');
 
show create table xuesheng\G

2.1.4.3        查询刚刚产生的主键值

last_insert_id() 函数

获取最后一个自动产生的主键值

只获得当前客户端产生的主键值

select last_insert_id();

2.1.4.4        取消主键的自增

alter table xuesheng
modify id int; -- auto_increment;
 
show create table xuesheng\G

2.1.5  主键的索引

索引以特定结构(B-tree)存放数据,通过索引定位数据,效率非常高

主键自动创建索引数据

2.2    外键

约束一个字段的取值,只能取另一个主键中存在的值

创建外键约束时,会同时创建索引

外键减少数据冗余,但会降低数据访问效率,

外键要做数据做约束检查,也会降低效率,高并发系统中,尽量避免使用外键

分类

1

服装

2

电脑

3

手机

商品表

id

名称

分类编号(fk)

1

a

1

2

b

null

3

c

2

4

d

2

商品表的分类编号字段,只能取分类表主键中存在的值,而不能随便取值

2.2.1  添加外键约束

l  建表时添加外键

create table tb2(
   ...,
   tb1_id int,
   foreign key(tb1_id)
references tb1(id)
);

l  修改表时添加外键

alter table tb2
add foreign key(tb1_id)
references tb1(id);

学生和班级

-- 班级表
drop table if exists banji;
create table banji(
   id int primary key auto_increment,
   name varchar(50)
) engine=innodb charset=utf8;

--  学生表
drop table if exists xuesheng;
create table xuesheng(
   id int primary key auto_increment,
   stu_id int,
   name varchar(50),
   ban_id int,
   foreign key(ban_id) references banji(id)
) engine=innodb charset=utf8;
 
 
--  向班级表插入数据
insert into banji(name) values('A'),('B');
select * from banji;

--  向学生表插入数据
insert into xuesheng(stu_id,name,ban_id)
values
(11,'张三', 1), (22,'李四', 2),(33,'王五',1);
--  foreign key constraint fails
--  (`db1`.`xuesheng`, CONSTRAINT
--  `xuesheng_ibfk_1` FOREIGN KEY
--  (`ban_id`) REFERENCES `banji` (`id`))
insert into xuesheng(stu_id,name,ban_id)
values(44,'赵六', 99);
 
select * from xuesheng;

2.2.2  查看外键约束

show create table xuesheng\G

2.2.3  删除外键约束

删除外键约束,会保留索引,如果要删除索引,需要再手动删除

alter table xuesheng
drop foreign key 外键约束名;

alter table xuesheng
drop index 索引名称;
alter table xuesheng
drop foreign key xuesheng_ibfk_1;

show create table xuesheng\G

alter table xuesheng
drop index ban_id;

show create table xuesheng\G

2.3    非空

约束一个字段的取值,不能取null值

2.3.1  添加非空约束

l  建表时添加非空约束

create table tb1(
   ...,
   name varchar(20) not null,
   ...
);

l  修改表时添加非空约束

alter table tb1
modify name varchar(20) not null;

班级名和学生名非空

alter table banji
modify name varchar(50) not null;
 
alter table xuesheng
modify name varchar(50) not null;
--  Column 'name' cannot be null
insert into banji(name) values(null);
--  Column 'name' cannot be null
insert into xuesheng(name)
values(null);
 
insert into xuesheng(stu_id,name)
values(null, 'a');
 
--  存在null值的字段,不能添加非空约束
--  Data truncated for column 'stu_id'
alter table xuesheng
modify stu_id int not null;

2.3.2  查看非空约束

desc banji;
 
show create table banji \G

2.3.3  删除非空约束

alter table banji
modify name varchar(50);
 
alter table banji
modify name varchar(50) null;
 
desc banji;

2.4    唯一

限制字段中的取值,不能出现重复值,但允许重复的null值

唯一约束本身会创建索引

2.4.1  添加唯一约束

l  建表时添加唯一约束 

create table tb1(
   ...,
   email varchar(100) unique,
   ...
);
 
create table tb1(
   ...,
   email varchar(100),
   ...,
   unique key(email)
);

设置两个字段组合唯一

create table tb1(
   ...,
   ip varchar(100),
   username varchar(20)
   ...,
   unique key(ip, username)
);

l  修改表时添加唯一约束

alter table tb1
modify name varchar(20) unique;
 
alter table tb1
add unique key(name);

学生的学号不重复

alter table xuesheng
add unique key(stu_id);
--  插入重复的学号
--  Duplicate entry '11' for key 'stu_id'
insert into xuesheng(stu_id,name)
values(11, 'a');

2.4.2  查看唯一约束

desc xuesheng;

show create table xuesheng\G

2.4.3  删除唯一约束

-- alter table xuesheng
-- drop index 索引名;

alter table xuesheng
drop index stu_id;
 
desc xuesheng;
show create table xuesheng\G

2.5    检查(mysql不支持)

mysql 可以执行检查约束语法,但是没有实现检查约束

create table tb1(
   ...,
   age int,
   gender char(1),
   ...,
   check(age>=16 and age<=60),
   check(gender='M' or gender='F'),
   check(gender in('M', 'F'))
);

2.6    默认值

字段中插入数据时,如果不提供数据,自动取默认值

create table tb1(
   ...,
   status tinyint default 2,
   ...
);

3   表之间的关系

3.1    一对一

具有唯一约束的外键字段

学生的联系方式表

create table lianxi(
   xid int primary key,
   tel varchar(20),
   qq varchar(20),
   weixin varchar(100),
   foreign key(xid)
references xuesheng(id)
)engine=innodb charset=utf8;
 
select * from xuesheng;
 
insert into lianxi(xid, tel) values
(1,'2634563456'), (3, '234523423');

3.2    一对多

可重复的外键字段

学生的组长

--  学生表添加组长id字段
alter table xuesheng
add(
   zuzhang int,
   foreign key(zuzhang)
      references xuesheng(id)
);
 
select * from xuesheng;
 
update xuesheng set zuzhang=1
where id=2;
 
update xuesheng set zuzhang=3
where id=5;
 
select * from xuesheng;

3.3    多对多

关系中间表,设置两个外键,分别应用两张表的主键

学生和课程的多对多关系

create table kecheng(
   id int primary key auto_increment,
   name varchar(20)
)engine=innodb charset=utf8;
 
create table xs_kc_link(
   xid int not null,
   kid int not null,
   unique key(xid, kid),
   foreign key(xid)
references xuesheng(id),
   foreign key(kid)
references kecheng(id)
)engine=innodb charset=utf8;
 
 
insert into kecheng(name) values
('语文'),('数学'),('英语');
 
insert into xs_kc_link values
(1,1),(1,2),(1,3),(2,1),
(2,3),(3,1),(3,2),(5,2);
 
select * from kecheng;
 
select * from xs_kc_link;

4   SQL

结构化的查询语言

Structured Query Language

l  DDL - 数据定义,建库建表

l  DML - 数据操作,增删改

l  DQL - 数据查询,select

5   insert

插入数据

l  insert into tb1 values(值1,值2...)

l  insert into tb1(c1,c2) values(值1,值2)

l  insert into tb1 values(),(),(),();

l  批量数据插入

n  将查询结果,插入到以一个表中

insert into tb1(c1,c2)

select c1, c2 from tb2;

n  可以在同表中复制数据

insert into tb1(c1,c2)

select c1, c2 from tb1;

  

n  将查询结果创建成一张表

create table xuesheng3

as  --  as可以省略

select * from xuesheng;

批量插入测试

--  课程表数据复制
insert into kecheng(name) select name from kecheng;

6   update

update tb1 set

   字段1=值1,

   字段2=值2,

   字段3=值3,

   字段4=值4

where 过滤条件

l  特殊修改:

按指定数据进行排序,排序后,只修改前几条数据

update tb1 set 字段=值, 字段=值

order by 字段

limit 5

最新加入的两个学生,去2班

update xuesheng set ban_id=2
order by id desc
limit 2;
 
select * from xuesheng;

7   delete

delete from tb1

where 条件

l  特殊的删除方式:

按指定字段排序,取前几条删除

delete from tb1

order by 字段

limit 5

随机删除一个学生

select rand(); --  [0,1)范围的随机值
 
delete from xuesheng3
order by rand()  --  随机排序
limit 1;
 
select * from xuesheng3;

8   作业

4.2.1 商品分类表(tb_item_cat)

id 自增主键

parent_id  外键,引用当前表的主键

status和is_parent的默认值

 

4.2.2 商品表(tb_item)

id 自增主键

cid 非空,外键,引用分类表的主键

status的默认值

 

4.2.3 商品描述表(tb_item_desc)

item_id 主键,外键,引用商品id


03: 常用函数、分页、触发器

8    作业

1   select查询

select 字段1,字段2...

from 表

where 条件

select * from 表 where 条件

2   where子句 - 过滤条件

=

等值过滤

<> 

不等

> >= < <=

比较大小

between 小 and 大

c>=小 and c<=大

and

并且

or

或者

in

在指定的一组值中取值, in(50,10,80,30)

is null

is not null

null 值过滤

like

字符串模糊匹配

通配符:

% 任意多个字符

_ 任意单个字符

\ 对通配符进行转义

\_ 匹配一个下划线

\% 匹配一个百分号

\\ 匹配一个斜杠字符

not

not between and

not in

not like

is not null

准备测试数据

--  hr_mysql.sql复制到d:盘根目录
 
source d:\hr_mysql.sql  --  没有分号
 
show databases;  --  hr库
show tables;
 
select * from employees;

where 过滤测试

--  1. 查询员工的id,first_name,salary
select
   employee_id, first_name, salary
from employees;
 
--  2. 查询员工编码 110
select
   employee_id, first_name, salary
from employees
where employee_id=110;
 
--  3. job_id工作岗位代码是 'IT_PROG'
select
   employee_id, first_name, salary,
   job_id
from employees
where job_id='IT_PROG';
 
 
--  4. 部门id是30
select
   employee_id, first_name, salary,
   department_id
from employees
where department_id=30;
 
 
--  5. 部门id不是50部门
select
   employee_id, first_name, salary,
   department_id
from employees
where department_id<>50;
 
 
--  6. 薪水大于等于 20000
select employee_id,first_name,salary
from employees
where salary>=20000;
 
-- 7.薪水小于等于3000或大于等于20000
select employee_id,first_name,salary
from employees
where salary<=3000 or salary>=20000;
 
 
--  8. 薪水8000到10000
select employee_id,first_name,salary
from employees
where salary between 8000 and 10000;
-- where salary>=8000
-- and salary<=10000;
 
 
--  9. first_name 是Jason, John, Peter
select employee_id,first_name,salary
from employees
where first_name
in('Jason','John','Peter');
 
 
--  10. 部门id是90,100,80
select
employee_id,first_name,salary,department_id
from employees
where department_id in(90,100,80);
 
--  11. job_id是ST_MAN, HR_REP, AC_ACCOUNT
select
employee_id,first_name,salary,job_id
from employees
where job_id
in('ST_MAN','HR_REP','AC_ACCOUNT');
 
 
--  12. 部门id是null值
select
employee_id,first_name,salary,department_id
from employees
where department_id is null;
 
--  13. 有提成,提成比例不是 null
select
employee_id,first_name,salary,
job_id,commission_pct
from employees
where commission_pct is not null;
 
--  14. first_name中包含en
select
employee_id,first_name,salary
from employees
where first_name like '%en%';
 
--  15. first_name 第3第4个字符是en
select
employee_id,first_name,salary
from employees
where first_name like '__en%';
 
--  16. JOB_ID 第2第3个字符是 A_
select
employee_id,first_name,salary,job_id
from employees
where job_id like '_A\_%';
 
 
--  17. 工资不在 [5000, 18000]
select
employee_id,first_name,salary
from employees
where salary
not between 5000 and 18000;
 
--  18. 部门id不是30,50,80
select
employee_id,first_name,salary,
department_id
from employees
where department_id not in(30,50,80)
or department_id is null;
 
 
--  19. first_name 中不包含a
select employee_id,first_name,salary
from employees
where first_name not like '%a%';

3   distinct - 去除重复值

-- 指定字段去除重复值
select distinct 字段 from 表

-- 字段组合去除重复值
select distinct 字段1,字段2 from 表

 distinct 在字段列表前面,只出现一次

distinct去除重复值

--  20.部门id
select distinct department_id
from employees
where department_id is not null;
--  21.job_id
select distinct job_id
from employees;
--  22.部门id,job_id
select distinct department_id, job_id
from employees
where department_id is not null;
--  23.50部门中有哪些工作岗位
select distinct job_id
from employees
where department_id=50;

4   order by 子句 - 排序

select

from

where

order by

order by 字段1

   按字段1升序排列

order by 字段1,字段2

   先按字段1升序,字段1相同,再按字段2升序

l  asc   升序(默认)

l  desc  降序

order by 字段 desc

order by 字段1 desc,字段2 desc

排序测试

--  24.所有员工按工资从大到小
select employee_id,first_name,salary
from employees
order by salary desc;
 
--  25.按部门升序,相同部门按工资降序
select
employee_id,first_name,
department_id,salary
from employees
order by department_id,salary desc;
 
--  26.主管是100,按部门和工资排序
select
employee_id,first_name,manager_id,
department_id,salary
from employees
where manager_id=100
order by department_id,salary;

5   字段别名

为查询结果中的列,可以起一个别名

select 字段1 as 别名1,

        字段2 别名2,

        表达式 别名3

from ...

l  where 后面不能使用字段别名

sql语句处理顺序

1)  where 过滤

2)  select选取字段

3)  order by排序

n  其他数据库where可以用字段别名

别名

--  27.查询姓名 first_name,last_name连在一起
select
employee_id,
concat(first_name, ' ',last_name) name,
salary
from employees
order by name;
 
--  28.年薪>=100000,按年薪排序
select
employee_id, first_name, salary,
salary*12  sal
from employees
where  salary*12>=100000
order by sal;
 

6   练习

-- 查询 first_name 第三个字符是 e 的员工
select employee_id,first_name,salary from employees where first_name like '__e%';
 
-- 查询工种(job_id)以 SA 开头的员工
select employee_id,first_name,salary,job_id from employees where job_id like 'SA%';
 
-- 没有上司的员工,manager_id是null
select employee_id,first_name,salary,manager_id from employees where manager_id is null;
 
-- 部门 50 中,薪水大于等于 5000  的员工
select employee_id,first_name,salary,department_id from employees where department_id=50 and salary>=5000;
 
-- 姓名中有 en ,且在80 部门中的员工
select employee_id,first_name,last_name,salary,department_id from employees
where department_id=80 and
(first_name like '%en%' or last_name like '%en%');
 
-- 部门90中所有员工,和工种后缀是 CLERK 的员工
select employee_id,first_name, salary,department_id,job_id from employees where department_id=90 or job_id like '%CLERK';
 
-- 薪水大于等于 10000  的员工,按姓名排序
select employee_id,first_name,last_name salary from employees where salary>10000 order by first_name,last_name;

7   函数

7.1    字符串函数

      

        char_length('a中') - 字符数
        length('a中') - 字节数
        concat('a','b','cde','fff') - 字符串连接,其他数据库可用 || 连接字符串,'abc' || 'def'
        concat_ws(';','abc','def','ggg') - 用分隔符连接字符串   
        instr('abcdefgdef','def') - 返回第一个子串的位置,从1开始,找不到返回0
        locate('abc', '---abc---abc---abc-') - 返回第一个子串的位置,从1开始,找不到返回0
        locate('abc', '---abc---abc---abc-',5) - 从指定位置向后找
        insert('abcdefghijkl',2, 11, '---') - 用子串取代从2位置开始的11个字符
        lower('AdFfLJf') - 变为小写
        upper('AdFfLJf') - 变为大写
        left('AdFfLJf',3) - 返回最左边的三个字符
        right('AdFfLJf',3) - 返回最右边的三个字符
        lpad('abc', 8, '*') - 左侧填充到8个字节,指定长度比源字符串少,相当于left
        rpad('abc', 8, '*') - 右侧填充到8个字节,指定长度比源字符串少,相当于left
        trim('  a  bc   ') - 去除两端空格
        substring('abcdefghijklmn', 3) - 从3位置开始的所有字符
        substring('abcdefghijklmn', 3, 6) - 从3位置开始的6个字符
        repeat('abc', 3) - 重复三遍abc
        replace('Hello MySql','My','Your') - 子串替换
        reverse('Hello') - 翻转字符串
        space(10) - 返回10个空格

字符串函数测试

set names gbk;
--  服务器会记住客户端是gbk编码
--  在服务器端会修改三个环境变量
--  客户端编码、连接编码、发送的结果编码
show variables like '%char%';
 
select char_length('a中');
set names latin1;
select char_length('a中');
set names gbk;
 
select length('a中');
select concat('abc', 'def', 'ghi');
select concat_ws(';', 'abc', 'def', 'ghi');
select locate('abc', '--abc--abc--abc--');
select locate('abc', '--abc--abc--abc--', 4);
select insert('abcdefghijk',2,10,'***');
select lower('AbCdEf');
select upper('AbCdEf');
select left('AbCdEf',3);
select right('AbCdEf',3);
select lpad('abc',8, '*');
select rpad('abc',8, '*');
select trim('  ab  cd  ');
select substring('abcdefghijk', 3);
select substring('abcdefghijk', 3, 6);
select repeat('abc',3);
select replace('abcdefghijk','def','--');
select reverse('hello');
select space(10);

用字符串函数查询

-- 29. first_name和last_name首字母相同
-- left(first_name,1)
-- substring(first_name,1,1)
select
employee_id,first_name,last_name,salary
from employees
where substring(first_name,1,1)=
substring(last_name,1,1);
 
-- 30. first_name和last_name长度相同
select
employee_id,first_name,last_name,salary
from employees
where char_length(first_name)=
char_length(last_name);
 
-- 31. email不是用first_name首字母+last_name
select
employee_id,first_name,last_name,
salary,email
from employees
where email<>
concat(left(first_name,1),
replace(last_name,' ',''));
 
-- 32. 连接姓名,空格居中显示
select
concat(lpad(first_name,20,' '),
' ',last_name) name
from
employees;

7.2    数字函数

        ceil(3.14) -- 天花板,向上取整
        floor(3.94) -- 地板,向下取整
        format(391.536, 2) -- 数字格式化为字符串,###,###.###,四舍五入,第二个参数为小数位数
        round(673.4974) -- 四舍五入
        round(673.4974, 2) -- 四舍五入到小数点后两位
        round(673.4974, -2) -- 四舍五入到百
        truncate(234.39, 1) -- 舍去至小数点后1位
        rand() -- 随机浮点数[0,1)

数字函数测试

select ceil(3.14);
select ceil(-3.14);
select round(373.8856);
select round(373.8856, 2);
select round(373.8856, -2);
select truncate(373.8856, 2);
select rand();

用数字函数查询

-- 33. 涨工资10.41%,向上取整到十位
select
employee_id,first_name,salary,
ceil(salary*1.1041/10)*10 sal
from
employees;

7.3    日期函数

mysql 中日期类型与字符串类型可以自动转换

转换条件:日期是'%Y-%m-%d'默认格式

NOW()   返回当前的日期和时间

        CURDATE()   返回当前的日期

        CURTIME()   返回当前的时间

        DATE(时间)   提取日期或日期/时间表达式的日期部分

        TIME(时间)    提取日期或日期/时间表达式的时间部分

        EXTRACT(字段 From 日期)   返回日期/时间按的单独部分

            字段的合法值:

                  MICROSECOND

                  SECOND

                  MINUTE

                  HOUR

                  DAY

                  WEEK

                  MONTH

                  QUARTER

                  YEAR

                  SECOND_MICROSECOND

                  MINUTE_MICROSECOND

                  MINUTE_SECOND

                  HOUR_MICROSECOND

                  HOUR_SECOND

                  HOUR_MINUTE

                  DAY_MICROSECOND

                  DAY_SECOND

                  DAY_MINUTE

                  DAY_HOUR

                  YEAR_MONTH

        DATE_ADD(日期, INTERVAL 数量 字段)   给日期添加指定的时间间隔

            字段的合法值同上

           

        DATE_SUB(日期, INTERVAL 数量 字段)   从日期减去指定的时间间隔

        DATEDIFF(日期1, 日期2)   返回两个日期之间的天数

        DATE_FORMAT(日期, 格式)   用不同的格式显示日期/时间

            格式字符:  %Y-%m-%d %H:%i:%s

                        %d/%m/%Y

                        %Y年%m月%d日

                    %a  缩写星期名

                    %b  缩写月名

                    %c  月,数值

                    %D  带有英文前缀的月中的天

                    %d  月的天,数值(00-31)

                    %e  月的天,数值(0-31)

                    %f  微秒

                    %H  小时 (00-23)

                    %h  小时 (01-12)

                    %I  小时 (01-12)

                    %i  分钟,数值(00-59)

                    %j  年的天 (001-366)

                    %k  小时 (0-23)

                    %l  小时 (1-12)

                    %M  月名

                    %m  月,数值(00-12)

                    %p  AM 或 PM

                    %r  时间,12-小时(hh:mm:ss AM 或 PM)

                    %S  秒(00-59)

                    %s  秒(00-59)

                    %T  时间, 24-小时 (hh:mm:ss)

                    %U  周 (00-53) 星期日是一周的第一天

                    %u  周 (00-53) 星期一是一周的第一天

                    %V  周 (01-53) 星期日是一周的第一天,与 %X 使用

                    %v  周 (01-53) 星期一是一周的第一天,与 %x 使用

                    %W  星期名

                    %w  周的天 (0=星期日, 6=星期六)

                    %X  年,其中的星期日是周的第一天,4 位,与 %V 使用

                    %x  年,其中的星期一是周的第一天,4 位,与 %v 使用

                    %Y  年,4 位

                    %y  年,2 位

        LAST_DAY(日期) - 返回当月最后一天

日期函数测试

select now();  -- 当前年月日时分秒
select curdate(); -- 当前年月日
select curtime(); -- 当前时分秒
select date(now()); -- 提取日期
select time(now()); -- 提取时间
select extract(year from now()); -- 提取年号
select extract(month from now()); -- 提取月号
select extract(day from now()); -- 提取日
--  加10年
select date_add(now(), interval 10 year);
--  减10年
select date_add(now(), interval -10 year);
--  相差天数
select datediff(now(), '1996-7-21');
--  相差天数,负数
select datediff('1996-7-21', now());
--  日期格式化
select date_format(now(),'%Y-%m-%d %H:%i:%s');
select date_format(now(),'%d/%m/%Y %H:%i:%s');

用日期函数查询

-- 34. 入职30年以上的员工
select
employee_id,first_name,salary,hire_date
from employees
where hire_date<=
date_add(now(),interval -30 year);
 
-- 35. 1997年上半年入职的人
select
employee_id,first_name,salary,hire_date
from employees
--  where hire_date
--  between '1997-1-1' and '1997-6-30';
where extract(year from hire_date)=1997
and extract(month from hire_date)<7;
 
-- 36. 不论哪一年,所有1月份入职的人
select
employee_id,first_name,salary,hire_date
from employees
where extract(month from hire_date)=1;

7.4    null值处理

IFNULL(数据1,数据2) - 数据1是null返回数据2;不是null返回数据1

coalesce(数据1,数据2,数据3,......) - 从左向右第一个不是null的数据

用null值处理函数查询

--  37.年薪,加提成
select
employee_id,first_name,salary,
salary*12*(1+ifnull(commission_pct,0)) sal
from employees;

7.5    加密

7.6    分支

7.7    多行函数

8   作业

用户表(tb_user)

id自增主键

username、password非空

username 唯一

phone和email 唯一

password的类型,改成 char(32)

收藏夹表(tb_collect)

id自增主键

user_id 外键,引用用户

item_id 外键,引用商品

status 默认值

  

购物车表(tb_cart)

id 自增主键

user_id 外键,引用用户

item_id 外键,引用商品

num 默认值

查询语句重复练习


04: 视图、存储过程、客户端工具SQLyog

5    作业

1   函数(续)

1.1    加密函数

md5()   

将数据加密成32个16进制数字字符

l  密码加密

l  文件的md5码

sha()

   比md5更安全的加密方式

加密函数测试

select md5('asdfas');
select sha('erfghed');

1.2    分支函数

if(条件, 1, 2)  条件成立返回1,否则返回2
 
case
   when 条件1 then ...
   when 条件2 then ...
   else ...
end;
 
case 字段或表达式
   when 值1 then ...
   when 值2 then ...
   else ...
end

分支测试

select if(floor(rand()*2)=0, 100, 200);
 
--  员工薪水,>=15000,显示“有钱”
--  >=3000,显示“小康”
--  否则,显示“穷B”
use hr;
set names gbk;
select employee_id,first_name,salary,
   case
      when salary>=15000 then '有钱'
      when salary>=3000 then '小康'
      else '穷B'
   end c
from employees
order by salary desc;

2   多行函数

多行数据,进行运算,产生一个结果

l  count()   行数

l  sum()     累加求和

l  avg()     平均

l  max()     最大

l  min()     最小

l  多行函数,不能和其他字段一起查询

mysql能一起执行其他字段查询,就是将数据中第一行数据查出来,

其他数据库不能执行

l  多行函数会忽略null值

l  count(字段) 和count(*)

n  count(字段)  对字段中的数据计数

n  count(*)  对行计数

l  count(distinct 字段) 去除重复记数

多行函数测试

select min(salary) from employees;
 
select min(salary),employee_id,first_name
from employees;
select
   count(salary),
   sum(salary),
   avg(salary),
   max(salary),
   min(salary)
from employees;
 
select count(commission_pct), -- 35
        avg(commission_pct)  -- 对35人求平均
from employees;
 
--  50部门的人数
select count(*)
from employees where department_id=50;
 
--  有多少个部门
select count(distinct department_id)
from employees;

用多行函数查询

-- 1. 有多少个部门,有多少个主管
select count(distinct department_id),
      count(distinct manager_id)
from employees;
-- 2. 员工人数,表中的行数
select count(*) from employees;
-- 3. 1997 年入职的人数
select count(*) from employees
where extract(year from hire_date)=1997;
-- 4. 最后进公司的人的入职时间
select max(hire_date) from employees;
-- 5. 122号员工是个主管,他的手下有多少人
select count(*) from employees
where manager_id=122;

2.1    group by分组计算多行函数

按指定的条件进行分组,分组后,每一组数据求多行函数产生一个结果

group by 子句

group by 字段

-- 按指定字段相同的值,进行分组

group by 字段1,字段2

-- 按指定字段列表的组合来分组

group by 必须是在做多行函数查询是进行分组

-- 分组的字段,可以和多行函数一起查询

分组求多行函数测试

--  6. 每个部门的人数,过滤null值,按人数排序
select department_id, count(*) c from employees
where department_id is not null
group by department_id
order by c;
 
-- 7. 每种工作的平均工资 job_id
select job_id, avg(salary)
from employees
group by job_id;
-- 8. 每年的入职人数(提取年号进行分组)
select extract(year from hire_date) year,count(*) c
from employees
group by year
order by c;
-- 9. 按月份分组计算人数
select
extract(year from hire_date) year,
extract(month from hire_date) month,
count(*) c
from employees
group by year,month
order by year,month;

2.2    having 子句,对多行函数过滤

select count(*) c
from ...
where ...
group by ...
having c=1
  • having对多行函数结果进行过滤
  • 普通过滤条件,用 where
  • having必须跟在group by之后

having过滤

--  10. 只有一个人的部门
select department_id,count(*) c
from employees
where department_id is not null
group by department_id
having c=1;
 
--  11. 只有一个人入职的年份
select extract(year from hire_date) year, count(*) c
from employees
group by year
having c=1;
 
--  12. 平均工资大于10000的工作
select job_id,avg(salary) avg
from employees
group by job_id
having avg>10000;

3   子查询

在查询中,嵌套查询

三类子查询:

  • 条件子查询,where 后面
  • 行内视图,from后面
  • select 后面

3.1    条件子查询

一个查询的查询结果,作为另一查询的过滤条件

  • 单值子查询

=

<> 

  • 多值子查询

in

> all(4,2,7,3) 大于最大

> any(4,2,7,3) 大于最小

  • 多列子查询

where (字段1,字段2)=(5,8)

条件子查询

--  13. 拿最低工资的员工
--  1)求最低工资
--  2)用最低工资过滤员工
select min(salary) from employees;
 
select employee_id,first_name,salary
from employees where salary=2100;
 
select employee_id,first_name,salary
from employees where salary=(
select min(salary) from employees
);
 
--  14. 工资低于平均工资
--  1)求出平均工资
--  2)用平均工资过滤员工
select avg(salary) from employees;  --  6461.682243
 
select employee_id,first_name,salary
from employees where salary<6461.682243;
 
 
select employee_id,first_name,salary
from employees where salary<(
select avg(salary) from employees
);
 
--  15. 最后入职的人
--  1)求最大入职时间
--  2)用最大时间,过滤员工
select max(hire_date) from employees;  --  2000-04-21
 
select employee_id,first_name,salary,hire_date
from employees where hire_date='2000-04-21';
 
select employee_id,first_name,salary,hire_date
from employees where hire_date=(
select max(hire_date) from employees
);
 
--  16. 只有一个人的部门中的员工信息
-- 1) 分组查询部门人数,并过滤人数是1
-- 2) 用查出的部门id过滤查询员工
select department_id -- ,count(*) c
from employees
where department_id is not null
group by department_id
having count(*)=1;
 
select employee_id,first_name,salary,department_id
from employees
where department_id in(
select department_id
from employees
where department_id is not null
group by department_id
having count(*)=1
);
 
 
--  17. 每个部门拿最高工资的员工信息
--  1)按部门分组求最高工资
--  2)用查询结果过滤,再查询员工
select department_id, max(salary)
from employees
where department_id is not null
group by department_id;
 
 
select employee_id,first_name,salary,department_id
from employees
where (department_id,salary) in(
select department_id, max(salary)
from employees
where department_id is not null
group by department_id
);
 

3.2    from后面的子查询,行内视图

将一个查询结果,当做一张表,从这张表再次查询

from子查询

--  18. 人数最多的部门的人数
--  1)分组求人数
--  2)得到最大人数
select department_id d,count(*) c
from employees
where department_id is not null
group by d;
 
 
select max(c) from (
select department_id d,count(*) c
from employees
where department_id is not null
group by d
) t;
 
 
--  19. 人数最多的部门编号
--  按部门分组求人数,并过滤人数是45
select department_id d
from employees
where department_id is not null
group by d
having count(*)=45;
 
 
select department_id d
from employees
where department_id is not null
group by d
having count(*)=(
select max(c) from (
select department_id d,count(*) c
from employees
where department_id is not null
group by d
) t
);
 
 
--  20. 查询人数最多部门的所有员工
select employee_id,first_name,salary,department_id
from employees
where department_id in (
select department_id d
from employees
where department_id is not null
group by d
having count(*)=(
select max(c) from (
select department_id d,count(*) c
from employees
where department_id is not null
group by d
) t
)
);
 
 
--  21. 平均工资最低的工作岗位,做这些工作的人
--  1)按工作分组求平均
--  2)得到最低工资值
--  3)根据最低工资值得到工作岗位
--  4)用工作岗位查询员工
select employee_id, first_name, salary, job_id
from  employees
where job_id in(
   select job_id from employees
   group by job_id having round(avg(salary),2)=(
      select min(a) from (
         select round(avg(salary),2) a from employees
         group by job_id
) t
)
);

3.3    select 子查询

select 后面字段列表中,添加一个字段值,可以通过嵌套查询来得到值

select子查询

--  查询员工,添加一列显示平均工资
select employee_id,first_name,salary,
(select round(avg(salary),2) from employees) avg
from employees;

4   sql注入攻击

用户填写的数据中,使用单引号改变sql语句结构,达到攻击的目的

避免sql注入攻击,把单引号进行转义

单引号转义: 两个单引号,转义成一个单引号

sql注入攻击测试

--  创建用户表
 
use db1;
drop table if exists user;
create table user(
   id int primary key auto_increment,
   username varchar(20),
   password char(32)
)engine=innodb charset=utf8;
 
insert into user(username,password) values
('abc',md5('123')), 
('def',md5('456'));
 
select * from user;
 
--  界面上提示用户输入用户名和密码
--  用户名: abc   密码: 123
select * from user
where username='abc'
and password=md5('123');
 
--  sql注入攻击,用单引号,改变sql语句的结构
--  用户名: 1' or '1'='1 密码: 1') or '1'=('1
select * from user
where username='1' or '1'='1'
and password=md5('1') or '1'=('1');
 
--  避免sql注入攻击,把单引号替换成两个单引号
--  在程序中替换,1'' or ''1''=''1,
--  1'') or ''1''=(''1
select * from user
where username='1'' or ''1''=''1'
and password=md5('1'') or ''1''=(''1');
 
--  数据表中插入的数据中,包含单引号,
--  先替换,再插入
insert into user(username, password)
values('I''m ghi', md5('1''23'));
 
select * from user;

5   作业

4.2.4 商品规格参数表(tb_item_param)

商品规格模板

   电脑的规格参数:

      品牌:联想,Thinkpad,戴尔,华为

      cpu:i5,i7,i9

      内存:4G,8G,16G,32G

Item_cat_id 非空,外键引用分类表

 

4.2.5 商品规格与商品的关系表(tb_item_param_item)

具体商品的规格参数

   联想y480:

      品牌:联想

      cpu: i5

      内存:4G

item_id 非空,外键引用商品id

 

4.2.6 内容表(tb_content)

广告、新闻等

category_id 非空,外键引用内容分类表

4.2.7 内容分类表(tb_content_category)

parent_id  引用本表的id

status   默认值

is_parent 默认值

 

重复练习sql语句


05: 创建京淘电商中的所有数据库表之用户表和商品表

回顾

select

distinct

from

where

group by

having

order by

子查询

   条件子查询

      单行  = > <

      多行  in  >all  >any

      多列  (a,b)in两列查询

   from 子查询

      select ... from (select ...) t

   select 子查询

      select a,b,(select ...) from ...

  

1   多表查询

两张表通过指定的连接条件,连接成一张表

 

select

   A.a,A.b,A.c,

   B.a,B.b

from A, B

where A.xid=B.id

表连接查询

use hr;
set names gbk;
 
--  部门表
select * from departments;
--  员工,显示员工的部门名称
select
   e.employee_id,e.first_name,e.salary,
   d.department_id,d.department_name
from
   employees e, departments d
where
   e.department_id=d.department_id;
 
--  地区表
select * from locations;

 --  部门,显示部门所在的城市
select
   d.department_id,d.department_name,
   l.location_id,l.city
from
   departments d, locations l
where
   d.location_id=l.location_id;

--  员工,显示所在部门名称和城市
select
   e.employee_id,e.first_name,
   d.department_name,
   l.city
from
   employees e,
   departments d,
   locations l
where
e.department_id=d.department_id
and d.location_id=l.location_id;
 
--  用城市Seattle过滤查询员工
select
   e.employee_id,e.first_name,
   d.department_name,
   l.city
from
   employees e,
   departments d,
   locations l
where
e.department_id=d.department_id
and d.location_id=l.location_id
and l.city='Seattle';
 
--  每个城市的平均工资
select
   l.city, avg(e.salary)
from
   employees e,
   departments d,
   locations l
where
e.department_id=d.department_id
and d.location_id=l.location_id
group by l.city;
 
 
--  部门表的部门经理id 和 员工id

--  部门,和部门经理名
select
   d.department_id,d.department_name,
   e.first_name
from
   departments d,
   employees e
where
   d.manager_id=e.employee_id;
 
--  员工的主管id

--  员工,显示直接主管名
select
   e1.employee_id,e1.first_name,
   e2.first_name mgr
from
   employees e1,
   employees e2
where
   e1.manager_id=e2.employee_id;

--  员工,显示主管名和部门名
select
   e1.employee_id,e1.first_name,
   e2.first_name mgr,
   d.department_name
from
   employees e1,
   employees e2,
   departments d
where
   e1.manager_id=e2.employee_id
and e1.department_id=d.department_id;

2   标准表连接语法

非标准语法,对于外连接,没有统一的语法,不同数据库,都有各自的扩展语法

  • 内连接:

   连接条件内的数据,

   不符合连接条件的数据,会被过滤掉

  • 外连接:

   连接条件以外的数据,

   不符合连接条件的数据,也会被查出来

select

from a inner join b on 连接条件

       join c on 连接条件

where 过滤

  • 左外连接:

左侧表中,连接条件以外的数据

select

from a left outer join b on 连接条件

        left join c on 连接条件

  • 右外连接:

右侧表中,连接条件以外的数据

select

from a right outer join b on 连接条件

        right join c on 连接条件

  • 全外连接:

两张表中,条件以外的数据

select 

from a full outer join b on 条件

外连接测试

--  所有107个员工,显示部门名,没部门显示null
select
   e.employee_id,e.first_name,
   d.department_name
from
   employees e
left join departments d
   on e.department_id=d.department_id;

3   分页查询

分页查询没有标准sql,不同数据库使用自己的扩展语法

Mysql用 limit

  • limit 10    - 前10条
  • limit 0,10  - 从0条开始的10条
  • limit 10,10 - 从第11条开始的10条
  • limit 20,10 - 从第21条开始的10条
  • 查询第page页,每页size条

limit (page-1)*size, size

分页测试

select employee_id,first_name,salary from employees
limit 0,10;
 
select employee_id,first_name,salary from employees
limit 10,10;
 
select employee_id,first_name,salary from employees
limit 20,10;
 
select employee_id,first_name,salary from employees
limit 100,10;
  • 最大页数

数据条数/size

count(*)求数据条数,数据量大(>千万)时,效率不高

应该在系统空闲时,后台统计数据量,保存到一个单独的表中,

这个值有延迟性

4   事务(重要)

事务是数据操作的最小单元

事务由一组增删改查操作组合而成,这一组操作要么整体成功,要么整体失败

例如:

   转账 A --> B

   A账户金额-100,成功

   B账户金额+100,失败,回滚第一步操作

   整体事务失败

4.1    事务操作:

4.1.1  开始事务

begin;

start transaction;

开始事务后,执行的数据操作sql语句,会暂存在一个日志文件中

4.1.2  提交事务

commit;     事务结束

将日志中记录的sql操作,保存到数据表中,而且会清空日期

4.1.3  回滚事务

rollback;      事务结束

直接清空日志

事务测试

use db1;

select * from user;

客户端1

客户端2

begin;

begin;

insert into user(username)

values('a');

insert into user(username)

values('b');

select * from user;

select * from user;

commit;

select * from user;

commit;

select * from user;

客户端1

客户端2

rollback;

rollback;

begin;

begin;

insert into user(username)

values('c');

insert into user(username)

values('d');

select * from user;

select * from user;

rollback;

select * from user;

4.2    事务特性ACID(理论)

            A - 原子性 Atomic

                  事务是数据操作的最小单元

                  而不是SQL语句

            C - 一致性 Consistency

                    转账前 a+b = 100

                    转帐后 a+b = 100

            I - 隔离性 Isolation

                    一个事物进行中时,

                    另一事物不能操作数据

            D - 持久性 Durancy

                    提交事务之后,

                    数据持久生效

测试事务隔离

客户端1

客户端2

rollback;

begin;

rollback;

begin;

update user set password='111'

where id=6;

select * from user;

update user set password='222'

where id=6;

commit;

update user set password='222'

where id=6;

select * from user;

commit;

4.3    多个事务数据访问冲突

  • 脏读

A事务未提交的数据,被B事务读取

  • 不可重复读

A事务第一次查询数据后,再次查询相同数据,数据前后不一致

  • 幻读

A事务第一查询多行数据,

B事务删除一条数据并提交,

A事务重复查询,仍可以查到这条数据

A事务第一查询多行数据,

B事务插入一条数据并提交,

A事务重复查询,查询不到新数据

  

  

4.4    事务隔离级别

如果事务完全隔离,效率低,而完全不隔离,会有数据访问冲突,

为了兼顾效率和数据安全,数据库提供了不同的折中方案,可以让事务在不同的隔离级别下运行

隔离级别:

set tx_isolation='read-uncommitted';

读取未提交数据

脏读、不可重复读、幻读

set tx_isolation='read-committed';

读取已提交数据

不可重复读、幻读

set tx_isolation='repeatable-read';

可重复读,最佳(默认)折中方案

幻读

set tx_isolation='serializable';

序列化,串行化

事务完全隔离,排队依次执行

隔离级别测试

客户端1

客户端2

set

tx_isolation='read-uncommitted';

set

tx_isolation='read-uncommitted';

rollback;

begin;

rollback;

begin;

insert into user(username)

values('e');

update user set password='333'

where id=9;

select * from user;

select * from user;

rollback;

select * from user;

select * from user;

客户端1

客户端2

set tx_isolation='read-committed';

set tx_isolation='read-committed';

rollback;

begin;

rollback;

begin;

insert into user(username)

values('e');

update user set password='333'

where id=9;

select * from user;

select * from user;

commit;

select * from user;

客户端1

客户端2

set

tx_isolation=

'repeatable-read';

set

tx_isolation=

'repeatable-read';

rollback;

begin;

rollback;

begin;

select * from user;

delete from user

where id in(5,6,7);

commit;

select * from user;

select * from user;

update user

set password='111';

select * from user;

commit;

select * from user;

客户端1

客户端2

rollback;

begin;

rollback;

begin;

select * from user;

insert into user(username)

values('f');

commit;

select * from user;

select * from user;

update user

set password='456';

select * from user;

commit;

5   视图

将一个select查询语句,保存在数据库中,起个名字,以后可以从视图查询,本质就是执行保存的查询语句,再从查询结果中再查询

  • 视图不保存数据
  • 用视图可以简化查询
  • 安全:

可以对低级别用户隐藏数据表,只向他暴露视图

5.1    创建视图 

create view v1

as

select ...;

  • mysql的视图中不能出现子查询

创建视图

use hr;
 
create or replace view v1
as
select
   l.city, avg(e.salary) sal
from
   employees e,
   departments d,
   locations l
where
e.department_id=d.department_id
and d.location_id=l.location_id
group by l.city;
 
select * from v1;
 
select min(sal) from v1;

5.2    查看视图

show tables;
desc v1;
show create table v1\G
show create view v1\G

5.3    删除视图

drop view if exists v1;

6   索引

索引以特定结构(B-tree)存放数据,通过索引定位数据,效率非常高

如果要提高一个字段数据的查找效率,首选创建索引

where a=6343

      创建a字段的索引,对a过滤会使用索引

where a=63435 and b=74534

      可以对a,b字段组合创建索引,

      对a字段单独过滤也可以使用组合索引,对b字段单独过滤,不会使用组合索引

where a like 'abc%'

      对a创建索引,可以提高末尾的模糊匹配查询效率,

      '%def' 不会使用索引

6.1    创建索引

create index 命名 on 表(字段)

create index 命名 on 表(字段1,字段2)

创建索引

create index f_l_name_index on

employees(first_name, last_name);

6.2    explain

explain 确定一个查询语句是否使用索引来查找数据

explain select * from employees
where first_name like 'a%'
and last_name like 'k%';

explain select * from employees
where first_name like 'k%';

explain select * from employees
where last_name like 'k%';

6.3    查看索引

show create table employees\G

6.4    删除索引

alter table employees

drop index f_l_name_index;

7   作业

kecheng表,主键过滤查找一个id值

再测试删除主键,再查找id

tb_order 订单表

   order_id 主键

            流水号,由用户id,时间,随机值组成

   user_id 非空,外键引用用户

tb_order_item  订单商品表

   保存一个订单中,多个商品的信息

   id 主键,流水号

   item_id,外键,引用商品

   order_id,外键,引用订单

tb_order_shipping 订单物流表

   order_id,主键,外键,引用订单

     

tb_address  用户地址表

   id 自增主键

   添加字段 user_id, bigint加在 id 后面

  

多表查询重复练习


06: 综合项目实战

1   数据库编程(了解)

数据库中可以编写并保存一段程序,做数据运算

  • 存储过程
  • 函数
  • 触发器

mysql数据库编程能力较弱,很多功能无法实现

2   变量

2.1    用户会话变量

一个客户端与服务器连接期间的变量

set @v1 = 123;

select @v1;

2.2    局部变量

begin ... end; 是一对大括号,局部变量只能在 begin 到 end之间使用,end结束后,变量消失

使用 declare 关键字来定义局部变量

delimiter ;    结束符改成 ;

delimiter //      结束符改成//

begin

   declare v2 int default 123;

   select v2;

   select @v1;

end//

2.3    系统环境变量

只在本次回话有效

set character_set_client=''

set tx_isolation=''

对所有回话都有效,对全局有效,并永久保存,

对当前回话,不会立即生效,下次连接才生效

set global character_set_client=''

set global tx_isolation=''

3   存储过程

存储过程是存储在数据库服务器中的一段过程代码

3.1    定义存储过程

--  修改结束符
delimiter //
 
--  创建存储过程p1
create procedure p1()
begin  --  大括号开始
   -- 定义局部变量v2
   declare v2 int default 123;
   select v2; --  显示v2变量的值
end//  --  大括号结束

3.2    调用存储过程

call p1()//

3.3    查看存储过程

-- 所有存储过程
show procedure status\G
    
-- 查看指定库中的存储过程
show procedure status where db='db1'\G
    
 
show create procedure p1\G

3.4    删除存储过程

drop procedure if exists p1//

3.5    存储过程的参数

三种参数:

  • in       输入参数
  • out      输出参数
  • inout    既能输入又能输出

存储过程参数测试

--  向学生表和联系方式表同时插入数据
--  1) 插入学生数据
--  2) 得到新插入的自增主键值
--  3) 插入联系方式表
 
create procedure saveXuesheng
(in xid int, in name varchar(20),
in tel varchar(20), out id int)
begin
   declare v int;-- 定义临时变量用来存自增主键值
   --  插入学生数据
insert into xuesheng(stu_id,name)
   values(xid, name);
   --  获得新生成的自增主键值存到v
   set v = last_insert_id();
   --  插入联系方式数据
   insert into lianxi(xid,tel)
   values(v, tel);
   --  自增主键值存到输出参数id
   set id=v;
end//
 
 
--  调用
call  saveXuesheng
(34334,'张三','123123123',@stu_id)
//
 
select * from xuesheng//
select * from lianxi//
select @stu_id//

4   流程控制

4.1    if

if 条件 then
   代码
end if

if 条件 then
   代码1
else
   代码2
end if

4.2    case 

case
   when 条件1 then ...
   when 条件2 then ...
   else ...
end case
 
case 变量或表达式
   when 值1 then ...
   when 值2 then ...
   else
end case

分支判断测试

delimiter //
 
drop procedure if exists p1//
 
create procedure p1(in v int)
begin
   if v=1 then
      select 'v的值是1';
   end if;
   case v
      when 2 then select 'v的值是2';
      when 3 then select 'v的值是3';
      else select 'v的值不是2,3';
   end case;
end//
 
call p1(1) //
call p1(2) //
call p1(3) //
call p1(4) //

4.3    while

while 条件 do
   代码
end while

4.4    loop(死循环)

--  lp: 循环命名,可以起任意的名字
 
lp: loop
   ...
   if 条件 then
      leave lp; --  指定离开哪个循环
   end if;
   ...
end loop;

4.5    repeat

repeat
   代码
until 条件 end repeat;

循环测试

--  新建 tb1 表
use db1 //
 
drop table if exists tb1 //
 
create table tb1(
   id int primary key auto_increment,
   num int
)engine=innodb charset=utf8 //
 
drop procedure if exists p2//
create procedure p2(in n int)
begin
   declare i int default 0;
   --  while
   while i<n do -- i的值从0递增到n-1
      insert into tb1(num) values(i+1);
      set i=i+1;
   end while; 
   --  loop
   set i=0;
   lp: loop
      insert into tb1(num) values(i+1);
      set i=i+1;
      if i=n then -- i等于n时退出loop循环
         leave lp;
      end if;
   end loop;
   --  repeat
set i=0;
   repeat
      insert into tb1(num) values(i+1);
      set i=i+1;
   until i=n end repeat; -- i等于n时退出repeat循环
end//
 
call p2(10) //
 
select * from tb1 //

5   函数

l  函数有返回值

l  调用存储过程用call,

调用函数直接调

5.1    创建函数

create function f()
returns varchar(100)
begin
   执行代码运算产生计算结果
   return 计算结果;
end//

求平方的函数 fn_pow

drop function if exists fn_pow //
 
create function fn_pow(n int)
returns int -- 函数返回什么类型的数据
begin
   declare r int;
   set r = n*n;
   return r; -- 向调用位置返回计算结果
end //
 
select fn_pow(5) //
select *, fn_pow(num) from tb1 //

5.2    查看函数

show function status\G
show function status where db='test'\G
show create function f\G

5.3    删除函数*98

drop function if exists fn_pow //

随机字符串函数

定义函数 fn_randstr(a,b)
用来产生[a,b)长度范围的随机字符串
1)  定义保存长度的变量len
2)  产生随机长度floor(a+(rand()*(b-a)))存到变量len
3)  定义一个字符串包含所有可选字符
4)  定义一个保存结果的字符串,从空串“”开始
5)  定义一个位置变量,来表示随机字符的位置
6)  定义一个保存单个字符的变量
7)  循环len次
8)      产生随机位置
9)      得到一个随机字符
10)     将随机字符连接到结果中
 
drop function if exists fn_randstr;
 
create function fn_randstr(a int, b int)
returns varchar(255)
begin
   declare len int; -- 长度
-- 可选字符
   declare s0 varchar(600) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府称太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞';
   declare s varchar(255) default ''; -- 保存结果
   declare j int; -- 随机位置
   declare i int default 0; -- 循环次数控制
  
   -- 产生随机长度值[a,b)
   set len = floor(a+(rand()*(b-a)));
   -- 循环len次,产生len个字符
   while i<len do
      --  字符串s0范围内的随机位置
      set j=1+floor(rand()*char_length(s0));
      --  s后面连接s0中j位置的1个字符
      set s=concat(s, substring(s0,j,1));
      set i=i+1; -- i递增
   end while;
  
   return s;
end //
 
 
select fn_randstr(3,8) //

用存储过程在表中产生大量随机字符串

1)  创建一个内存表tm, engine=memory
2)  创建一个磁盘表td
3)  在存储过程中,循环20000次向内存表插入随机字符串
4)  把20000条数据,一批存入磁盘表
5)  清空内存表
 
--  内存表
drop table if exists tm;
create table tm(
   c varchar(20)
) engine=memory charset=utf8;
  
--  磁盘表
drop table if exists td;
create table td(
   id int primary key auto_increment,
   c varchar(20)
) engine=innodb charset=utf8;
--  存储过程
drop procedure if exists gen_data;
create procedure gen_data(in n int)
begin
   declare i int default 0; -- 用来控制循环次数
   while i<n do  -- 循环n次,产生n条数据
      -- 随机字符串插入内存表
      insert into tm values(fn_randstr(2,5));
      set i=i+1; -- i递增
   end while;
 
-- 内存数据批量存入磁盘表
   insert into td(c) select c from tm;
   delete from tm; -- 清空内存表
end //
 
call gen_data(5) //

用索引提高数据查找效率

--  没有索引,花3.5秒查询
select * from td where c='ab' //
 
--  对c字段创建索引,花1分40秒左右
create index td_c_index on td(c) //
 
--  有索引查询花费 0.00 秒
select * from td where c='ab' //

6   触发器

对表中的数据操作时,可以触发一段代码执行

三个数据操作:

  • index
  • update
  • delete

两个触发时间:

  • before
  • after

一张表中最多可以有6个触发器

  • before insert
  • after insert
  • before update
  • after update
  • before delete
  • after delete

两个隐含对象

  • new

新的数据行

insert的new:要插入的新行

update的new:修改后的新行

delete的new:没有

  • old

旧的数据行

insert的old:没有

update的old:修改前的旧数据

delete的old:被删除的旧数据

  • 访问新行或旧行数据:

new.id

new.name

old.age

old.tel

6.1    创建触发器

create trigger 名 触发时间 on 表
for each row
being
   代码
end;

用触发器自动更新updated字段

--  学生表添加 updated字段
alter table xuesheng
add updated datetime //
--  添加触发器,插入数据时自动填入时间
--  before insert
create trigger xs_before_insert
before insert on xuesheng for each row
begin
   set new.updated=now();
end //
 
insert into xuesheng(name)
values('a') //
 
select * from xuesheng //
 
--  添加触发器,修改数据时自动修改时间
create trigger xs_before_update
before update on xuesheng for each row
begin
   set new.updated=now();
end //
 
update xuesheng set ban_id=1
where name='a' //
 
select * from xuesheng //
 
 
--  不允许删除学生,删除学生时产生错误
--  before delete :删除之前触发
create trigger xs_before_delete
before delete on xuesheng for each row
begin
   --  阻止删除操作,手动产生一个错误
   --  mysql没有现成的产生错误的语法
   --  这里暴力产生错误
   delete from 不允许删除学生数据;
end //
 
delete from xuesheng where name='a' //

6.2    查看触发器

进入系统库 information_schema
use information_schema //
 
查询 triggers 表中触发器信息
select * from triggers\G

6.3    删除触发器

drop trigger 触发器名 //

7   数据库的备份、恢复

使用mysqldump命令备份数据库

使用mysql命令恢复数据库

7.1    备份

退出mysql,在系统命令行执行:

下面命令是一行代码,不能折行

mysqldump  -uroot -p

--default-character-set=utf8  //表中存的是什么编码

hr>d:\hr.sql  //库>文件

7.2    恢复

两步恢复:

1)  在数据库中新建一个库

create database jtdb2

charset utf8;

2)  在系统命令行执行恢复命令

下面命令是一行代码,不能折行

mysql -uroot -p

--default-character-set=utf8

jtdb2<d:\jtds.sql    

8   作业

商品表 tb_item

有什么品牌

最贵商品的品牌、名称、价格

分页查看商品

商品名和商品描述

商品分类表 tb_item_cat

查询所有的顶层分类

查询 161 下的二层分类

查询 162 下的三层分类

用户表

订单表

订单编号是 20161001490698615071

    查询没中类别的商品数量

    查询 类别 163 的商品

    查询商品价格不大于100的商品名称列表

    查询品牌是联想,且价格在40000以上的商品名称和价格

    查询品牌是三木,或价格在10以上的商品名称和价格

    查询品牌是三木、广博、齐心的商品名称和价格

    查询品牌不是联想、戴尔的商品名称和价格

    查找品牌是联想且价格大于10000的电脑名称

    查询联想或戴尔的电脑名称列表

    查询联想、戴尔、三木的商品名称列表

    查询不是戴尔的电脑名称列表

    查询所有是记事本的商品品牌、名称和价格

    查询品牌是末尾字符是'力'的商品的品牌、名称和价格

    名称中有联想字样的商品名称

    查询卖点含有'爆款'电脑名称

    查询开头字母是A的电脑名称

    将地址表中的城市、地区、详细地址组合到一起,

    获取订单编号为 20161001490698615071 中的每种商品的标题、单价、数量、总价

    统计商品表中各个品牌的商品数量

    统计商品表中各个品牌的商品数量,并且按照数量从少到多排序

    统计商品表中各个品牌的商品数量,去除品牌为NULL的行,并且按照数量从少到多排序

    查询不同品牌中最贵的商品价格

    将不同品牌中最贵的商品按照价格降序排序

    找出不同品牌中最贵的商品的前三名

  

    查询订购了10000028商品的客户姓名和联系方式(三层子查询)

         首先查询订单表,根据10000028这个商品编号找到有该商品的订单编号

         然后查询订单表,根据上面得到的订单编号找到订购此订单的用户编号

         最后查询用户表,根据第二部中查到的用户编号,找到对应的用户名和联系方式

    -- 查询没中类别的商品数量
    select cid,count(*) from tb_item group by cid;
   
    -- 查询 类别 163 的商品
    select id,title,price from tb_item where cid=163;
    -- 查询商品价格不大于100的商品名称列表
    select id,title,price from tb_item where price<100;
    -- 查询品牌是联想,且价格在40000以上的商品名称和价格
    select id,title,price from tb_item where brand='联想' and price>40000;
    -- 查询品牌是三木,或价格在50以下的商品名称和价格
    select id,brand,title,price from tb_item where brand='三木' or price<50;
    -- 查询品牌是三木、广博、齐心的商品名称和价格
    select id,brand,title,price from tb_item where brand in('三木','广博','齐心');
    -- 查询品牌不是联想、戴尔的商品名称和价格
    select id,brand,title,price from tb_item where brand not in('联想','戴尔');
    -- 查找品牌是联想且价格大于10000的电脑名称
    select id,brand,title,price from tb_item where brand='联想' and price>10000;
    -- 查询联想或戴尔的电脑名称列表
    select id,brand,title,price from tb_item where brand='联想' or brand='戴尔';
    -- 查询联想、戴尔、三木的商品名称列表
    select id,brand,title,price from tb_item where brand in('联想','戴尔','三木');
    -- 查询不是戴尔的电脑名称列表
    select id,brand,title,price from tb_item where brand<>'戴尔';
    -- 查询所有是记事本的商品品牌、名称和价格
    select id,brand,title,price from tb_item where title like '%记事本%';
    -- 查询品牌是末尾字符是'力'的商品的品牌、名称和价格
    select id,brand,title,price from tb_item where brand like '%力';
    -- 名称中有联想字样的商品名称
    select id,brand,title,price from tb_item where title like '%联想%';
    -- 查询卖点含有'爆款'电脑名称
    select id,brand,title,price from tb_item where cell_point like '%爆款%';
    -- 查询开头字母是A的电脑名称
    select id,brand,title,price from tb_item where title like 'A%';
    -- 将地址表中的城市、地区、详细地址组合到一起,
    select concat(receiver_city, receiver_district,receiver_address) addr from tb_address;
    -- 获取订单编号为 20161001490698615071 中的每种商品的标题、单价、数量、总价
    select title,price,num,total_fee from tb_order_item where order_id='20161001490698615071';
    -- 统计商品表中各个品牌的商品数量
    select brand,count(*) from tb_item group by brand;
    -- 统计商品表中各个品牌的商品数量,并且按照数量从少到多排序
    select brand,count(*) c from tb_item group by brand order by c;
    -- 统计商品表中各个品牌的商品数量,去除品牌为NULL的行,并且按照数量从少到多排序
    select brand,count(*) c from tb_item where brand is not null group by brand order by c;
    -- 查询不同品牌中最贵的商品价格
    select id,title,brand,price from tb_item where (brand,price) in(
      select brand,max(price) m from tb_item where brand is not null group by brand);
    -- 将不同品牌中最贵的商品按照价格降序排序
    select id,title,brand,price from tb_item where (brand,price) in(
      select brand,max(price) m from tb_item where brand is not null group by brand)
    order by price desc;
   
    -- 找出不同品牌中最贵的商品的前三名
    select id,title,brand,price from tb_item where (brand,price) in(
      select brand,max(price) m from tb_item where brand is not null group by brand)
    order by price desc
    limit 3;
   
     -- 查询订购了10000028商品的客户姓名和联系方式
     -- 首先查询订单表,根据10000028这个商品编号找到有该商品的订单编号
     -- 然后查询订单表,根据上面得到的订单编号找到订购此订单的用户编号
     -- 最后查询用户表,根据第二部中查到的用户编号,找到对应的用户名和联系方式
   
    select id, username, phone, email from tb_user where id in
      (select user_id from tb_order where order_id in
        (select order_id from tb_order_item where item_id=10000028))
   
   
    select
        distinct u.id, u.username, u.phone, u.email
    from
        tb_user u join tb_order o on u.id=o.user_id
                  join tb_order_item i on o.order_id=i.order_id
    where
i.                     item_id=10000028
 
 
  -- 商品表 tb_item
       
        select * from tb_item;
 
  -- 有什么品牌
       
        select distinct brand from tb_item;
 
  -- 最贵商品的品牌、名称、价格
       
        select brand,title,price
        from tb_item
        order by price desc
        limit 1;
 
  -- 分页查看商品
       
        select id,brand,title,price
        from tb_item
        order by price desc
        -- limit 0,10;
        -- limit 10,10;
        -- limit 20,10;
        limit 30,10;
 
  -- 商品名和商品描述
       
        select
            title,item_desc
        from
            tb_item i join tb_item_desc d
            on i.id=d.item_id
        limit 1;
 
  -- 商品分类表 tb_item_cat
       
        select * from tb_item_cat;
       
        select * from tb_item_cat
        where name like '%电脑%' or
              name like '%笔记本%' or
              name like '%手机%';
       
  -- 查询所有的顶层分类
       
        select * from tb_item_cat
        where is_parent=1 and parent_id is null;
 
  -- 查询 161 下的二层分类
       
        select * from tb_item_cat
        where parent_id=161 order by sort_order;
 
  -- 查询 162 下的三层分类
        select * from tb_item_cat
        where parent_id=162 order by sort_order;
 
  -- 用户表
        select * from tb_user;
 
  -- 订单表
        select * from tb_order;
       
  -- 用户 id 是14的订单
        select * from tb_order where user_id=14;
 
  订单编号是 20161001490698615071
  -- 查询这个订单的所有商品
     
        select * from tb_order_item
        where order_id=20161001490698615071;

08:Mysql思维导图


作者:Darren

电话:15110448224

QQ:603026148

以上内容归Darren所有,如果有什么错误或者不足的地方请联系我,希望我们共同进步。


猜你喜欢

转载自blog.csdn.net/weixin_39519454/article/details/84039365
今日推荐