2018.8.2
目录
day04
1,外键(foreign bey)
- 定义:让当前表字段的值在另一个表的范围内选择
- 语法
foreign key(参考字段名)
references 主表(被参考字段名)
on delete 级联动作
on updata 级联动作 - 使用规则
- 主表,从表字段数据类型要一致
- 主表被参考字段: 主键
- 示例
表1,缴费信息(财务表)
id 姓名 班级 缴费金额
1 唐伯虎 AID06 300
2 点秋香 AID06 260
3 祝枝山 AID06 250
表2,学生信息表(班主任)
id 姓名 缴费金额
1 唐伯虎 300
2 点秋香 260
3 XXXXXXXXXXX
1,创建表
表1:
create table jftab(
id int primary key,
name varchar(15),
class char(15),
money int
);
insert into jftab values
(1,'唐伯虎','AID06',300),
(2,'点秋香','AID06',260),
(3,'祝枝山','AID06',250);
表2(从表):
create table bjtab(
stu_id int,
name varchar(15),
money int,
foreign key(stu_id) references jftab(id)
on delete cascade
on update cascade
);
insert into bjtab values
(1,'唐伯虎',300),
(2,'点秋香',260);#顺序1 mysql> select * from jftab; +----+-----------+-------+-------+ | id | name | class | money | +----+-----------+-------+-------+ | 1 | 唐伯虎 | AID06 | 300 | | 2 | 点秋香 | AID06 | 260 | | 3 | 祝枝山 | AID06 | 250 | +----+-----------+-------+-------+ mysql> select * from bjtab; +--------+-----------+-------+ | stu_id | name | money | +--------+-----------+-------+ | 1 | 唐伯虎 | 300 | | 2 | 点秋香 | 260 | +--------+-----------+-------+ #删除点秋香 mysql> delete from jftab where name='点秋香'; mysql> select * from bjtab; +--------+-----------+-------+ | stu_id | name | money | +--------+-----------+-------+ | 1 | 唐伯虎 | 300 | +--------+-----------+-------+ #把唐伯虎id=2 mysql> update jftab set id=2 where name='唐伯虎'; mysql> select * from bjtab; +--------+-----------+-------+ | stu_id | name | money | +--------+-----------+-------+ | 2 | 唐伯虎 | 300 | +--------+-----------+-------+
- 删除外键
alter table 表名 drop foreign key 外键名;
外键名: show create table 表名;#顺序2 #获取外键值 mysql> show create table bjtab; +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | bjtab | CREATE TABLE `bjtab` ( `stu_id` int(11) DEFAULT NULL, `name` varchar(15) DEFAULT NULL, `money` int(11) DEFAULT NULL, KEY `stu_id` (`stu_id`), CONSTRAINT `bjtab_ibfk_1` FOREIGN KEY (`stu_id`) REFERENCES `jftab` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ #外键名就是 bjtab_ibfk_1 #删除外键名 alter table bjtab drop foreign key bjtab_ibfk_1;
- 级联动作
- cascade
数据级联删除,更新(参考字段) - restrict(默认)
- 当删除主表记录时,如果从表中有相关联记录则主表不允许删除
- 更新同理
- set null
主表删除,更新,从表相关联记录字段值为NULL
更新同理 - no action
on delete no action on update no action
同restrict,都是立即检查外键限制
- cascade
- 已有表中添加外键
alter table 表名 add
foreign key(参考字段名)references 主表(被参考字段)
on delete ...
on updata ...
#restrict(默认) 当删除主表记录时,如果从表中有相关联记录则主表不允许删除 更新同理 mysql> alter table bjtab add -> foreign key(stu_id) -> references jftab(id); Query OK, 1 row affected (0.06 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from jftab; +----+-----------+-------+-------+ | id | name | class | money | +----+-----------+-------+-------+ | 2 | 唐伯虎 | AID06 | 300 | | 3 | 祝枝山 | AID06 | 250 | +----+-----------+-------+-------+ 2 rows in set (0.00 sec) mysql> select * from bjtab; +--------+-----------+-------+ | stu_id | name | money | +--------+-----------+-------+ | 2 | 唐伯虎 | 300 | +--------+-----------+-------+ mysql> delete from jftab where name='唐伯虎'; ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`song`.`bjtab`, CONSTRAINT `bjtab_ibfk_1` FOREIGN KEY (`stu_id`) REFERENCES `jftab` (`id`)) #班级里面有外键关联,不允许删,所以只能先删班级里面的唐伯虎,再删缴费里面的唐伯虎 mysql> delete from bjtab where name='唐伯虎'; Query OK, 1 row affected (0.00 sec) mysql> delete from jftab where name='唐伯虎'; Query OK, 1 row affected (0.01 sec)
#set null #主表删除,更新,从表相关联记录字段值为NULL #更新同理 mysql> insert into bjtab values -> (3,'祝枝山',250); Query OK, 1 row affected (0.00 sec) mysql> select * from bjtab; +--------+-----------+-------+ | stu_id | name | money | +--------+-----------+-------+ | 3 | 祝枝山 | 250 | +--------+-----------+-------+ mysql> select * from jftab; +----+-----------+-------+-------+ | id | name | class | money | +----+-----------+-------+-------+ | 3 | 祝枝山 | AID06 | 250 | +----+-----------+-------+-------+ mysql> show create table bjtab; mysql> alter table bjtab drop foreign key bjtab_ibfk_1; mysql> alter table bjtab add -> foreign key(stu_id) -> references jftab(id) -> on delete set null -> on update set null; Query OK, 1 row affected (0.05 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> delete from jftab where name='祝枝山'; Query OK, 1 row affected (0.01 sec) mysql> select * from bjtab; +--------+-----------+-------+ | stu_id | name | money | +--------+-----------+-------+ | NULL | 祝枝山 | 250 | +--------+-----------+-------+
2,表的复制
- 表的重命名:alter table 表名 rename 新表名;
- 语法
create table 表名 select ... from 表名 where 条件; - 示例
- 复制MOSHOU.sanguo表的全部记录和字段,sanguo2
create table sanguo2
select * from MOSHOU.sanguo;
- 复制MOSHOU.sanguo表的前3条记录,sanguo3
create table sanguo3
select * from MOSHOU.sanguo
limit 3; - 复制MOSHOU.sanguo表的id,name,country 三个字段的前5条记录,sanguo4
create table sanguo4
select id,name,country from MOSHOU.sanguo
limit 5;
- 复制MOSHOU.sanguo表的全部记录和字段,sanguo2
- 复制表结构
create table 表名 select * from 表名 where false;- 复制MOSHOU.sanguo表结构 ,sanguo5
create table sanguo5
select * from MOSHOU.sanguo
where false;
- 复制MOSHOU.sanguo表结构 ,sanguo5
- 注意
- 复制表的时候不会把原表的 键(key) 属性复制过来
3,嵌套查询(子查询)
- 定义:把内层的查询结果作为外层的查询条件
- 语法格式
select ... from 表名 where 条件(select ...); - 示例
- 把攻击值小于平均攻击值的英雄名字和攻击值显示出来
- 先计算平均值
select avg(gongji) from MOSHOU.sanguo; - 找到 < 平均值
select name,gongji from MOSHOU.sanguo
where gongji < 平均值; - 这样写才对嘛
select name,gongji from MOSHOU.sanguo
where gongji < (select avg(gongji) from MOSHOU.sanguo);
- 先计算平均值
- 找出每个国家攻击力最高的英雄的名字和攻击值
第1种做法是无bug,第二种做法可能会出错
- select name,gongji from MOSHOU.sanguo
where (country,gongji) in
(select country,max(gongji) from MOSHOU.sanguo group by country);
- select name,gongji from MOSHOU.sanguo
where
gongji in (
select max(gongji) from MOSHOU.sanguo group by country);
- select name,gongji from MOSHOU.sanguo
- 把攻击值小于平均攻击值的英雄名字和攻击值显示出来
4,多表查询
- 两种方式
1,select 字段名列表 from 表名列表;(笛卡尔积)
t1:name-->'A1' 'A2' 'A3'
t2:name-->'B1' 'B2'
select * from t1,t2;+------+-------+ | name | name2 | +------+-------+ | A1 | B1 | | A1 | B2 | | A2 | B1 | | A2 | B2 | | A3 | B1 | | A3 | B2 | +------+-------+
2,...where 条件 - 练习 点击查看
- 显示省和市的信息
mysql> select sheng.s_name,city.c_name from sheng,city -> where -> sheng.s_id=city.cfather_id; +-----------+--------------+ | s_name | c_name | +-----------+--------------+ | 河北省 | 石家庄市 | | 河北省 | 沧州市 | | 河北省 | 廊坊市 | | 陕西省 | 西安市 | | 四川省 | 成都市 | | 四川省 | 重庆市 | | 广东省 | 广州市 | | 山东省 | 济南市 | | 湖北省 | 武汉市 | | 河南省 | 郑州市 | +-----------+--------------+
- 显示省,市和县的信息
mysql> select sheng.s_name,city.c_name,xian.x_name from sheng,city,xian -> where -> sheng.s_id=city.cfather_id and -> city.c_id=xian.xfather_id; +-----------+--------------+-----------+ | s_name | c_name | x_name | +-----------+--------------+-----------+ | 河北省 | 石家庄市 | 正定县 | | 湖北省 | 武汉市 | 武昌区 | +-----------+--------------+-----------+ 2 rows in set (0.00 sec)
- 显示省和市的信息
5,连接查询
- 内连接
- 语法格式
select 字段名 from
表1 inner join 表2 on 条件;
inner join 表3 on 条件 - 显示省市详细信息
select sheng.s_name,city.c_name from sheng
inner join city on sheng.s_id=city.cfather_id; - 显示省市县详细信息
select sheng.s_name,city.c_name,xian.x_name from sheng
inner join city on sheng.s_id=city.cfather_id
inner join xian on city.c_id=xian.xfather_id;
- 语法格式
- 外连接
- 左连接
- 以左为主显示查询信息
- select 字段名 from
表1 left join 表2 on 条件
left join 表3 on 条件; - 显示省和市详细信息
select sheng.s_name as sheng,city.c_name as city
from sheng left join city
on sheng.s_id=city.cfather_id;+-----------+--------------+ | sheng | city | +-----------+--------------+ | 河北省 | 石家庄市 | | 河北省 | 沧州市 | | 河北省 | 廊坊市 | | 陕西省 | 西安市 | | 四川省 | 成都市 | | 四川省 | 重庆市 | | 广东省 | 广州市 | | 山东省 | 济南市 | | 湖北省 | 武汉市 | | 河南省 | 郑州市 | | 海南省 | NULL | | 云南省 | NULL | | 山西省 | NULL | +-----------+--------------+
- 显示省,市和县的详细信息
select sheng.s_name as sheng,city.c_name as city,xian.x_name as xian
from sheng left join city
on sheng.s_id=city.cfather_id
left join xian on city.c_id=xian.xfather_id;
+-----------+--------------+-----------+ | sheng | city | xian | +-----------+--------------+-----------+ | 河北省 | 石家庄市 | 正定县 | | 湖北省 | 武汉市 | 武昌区 | | 河北省 | 沧州市 | NULL | | 河北省 | 廊坊市 | NULL | | 陕西省 | 西安市 | NULL | | 四川省 | 成都市 | NULL | | 四川省 | 重庆市 | NULL | | 广东省 | 广州市 | NULL | | 山东省 | 济南市 | NULL | | 河南省 | 郑州市 | NULL | | 海南省 | NULL | NULL | | 云南省 | NULL | NULL | | 山西省 | NULL | NULL | +-----------+--------------+-----------+
- 右连接
- 用法同左连接,以右边为主显示查询结果
- 显示省,市和县的详细信息
select sheng.s_name as sheng,city.c_name as city,xian.x_name as xian
from sheng right join city
on sheng.s_id=city.cfather_id
right join xian on city.c_id=xian.xfather_id;
+-----------+--------------+--------------+ | sheng | city | xian | +-----------+--------------+--------------+ | 河北省 | 石家庄市 | 正定县 | | 湖北省 | 武汉市 | 武昌区 | | NULL | 上海市 | 浦东新区 | | NULL | 雄安新区 | 安新县 | | NULL | 雄安新区 | 容城县 | | NULL | 雄安新区 | 雄县 | | NULL | NULL | 哈哈 | | NULL | NULL | 嘎嘎 | +-----------+--------------+--------------+
- 左连接
6、数据备份
(mysqldump,在Linux终端中操作)
- 命令格式
mysqldump -u用户名 -p 源库名 > ~/***.sql - 源库名的表示方式
--all-databases 备份所有库
库名 备份单个库
-B 库1 库2 库3 备份多个库
库名 表1 表2 表3 备份指定库的多张表 - 示例
1、备份所有库,放到 mydata 目录下:all.sql
mysqldump -uroot -p --all-databases > all.sql
2、备份 db4 库中的 sheng city xian 三张表,scx.sql
mysqldump -uroot -p db4 sheng city xian > scx.sql
3、备份 MOSHOU 和 db4 库, md.sql
mysqldump -uroot -p -B MOSHOU db4 > md.sql
4、备份 db4 库, db4.sql
mysqldump -uroot -p db4 > db4.sql
如果 不在当前文件运行 ,da4.sql前面加所在文件夹目录,可以cd 到当前文件,没有改文件就用mkdir+新文件,去创建
mysqldump -uroot -p db4 > ~/mydata/db4.sql - 注意
- ctrl+shift+t 重新打开一个终端
mkdir +文件名 :创建文件
cd +文件名 :改变当前路径
- ctrl+shift+t 重新打开一个终端
7、数据恢复
- 命令格式(Linux终端)
mysql -uroot -p 目标库名 < ***.sql - 从所有库备份中恢复某一个库(--one-database)
mysql -uroot -p --one-database 目标库名 < all.sql
mysql -uroot -p --one-database db4 < all.sql
mysql> drop database db4; Query OK, 0 rows affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | blog_db | | fruit | | fruitday | | mysql | | performance_schema | | sys | | testdb | | userorder | +--------------------+ 9 rows in set (0.00 sec) #没有此库,就创建一个新库 mysql> create database db4; Query OK, 1 row affected (0.00 sec) $mysqldump -uroot -p db4 > db4.sql
- 示例
- 在db4.sheng新增一条记录
mysql> insert into sheng values(11,200003,'日本三'); Query OK, 1 row affected (0.00 sec) mysql> select * from sheng; +----+--------+-----------+ | id | s_id | s_name | +----+--------+-----------+ | 1 | 130000 | 河北省 | | 2 | 140000 | 陕西省 | | 3 | 150000 | 四川省 | | 4 | 160000 | 广东省 | | 5 | 170000 | 山东省 | | 6 | 180000 | 湖北省 | | 7 | 190000 | 河南省 | | 8 | 200000 | 海南省 | | 9 | 200001 | 云南省 | | 10 | 200002 | 山西省 | | 11 | 200003 | 日本三 | | 16 | 3000 | 台湾省 | +----+--------+-----------+
- 在db4中新建一张表 t888,里面插入1条记录
create table t888( id int ); insert into t888 values(1); mysql> select * from t888; +------+ | id | +------+ | 1 | +------+
- 从db4.sql中恢复db4库
mysql -uroot -p db4 < db4.sql$mysql -uroot -p db4 < db4.sql mysql> show tables; +---------------+ | Tables_in_db4 | +---------------+ | bjtab | | city | | jftab | | jifei1 | | nam | | nam1 | | sanguo2 | | sanguo3 | | sanguo4 | | sanguo5 | | sheng | | t888 | | xian | +---------------+ mysql> select * from t888; +------+ | id | +------+ | 1 | +------+ mysql> select * from sheng; +----+--------+-----------+ | id | s_id | s_name | +----+--------+-----------+ | 1 | 130000 | 河北省 | | 2 | 140000 | 陕西省 | | 3 | 150000 | 四川省 | | 4 | 160000 | 广东省 | | 5 | 170000 | 山东省 | | 6 | 180000 | 湖北省 | | 7 | 190000 | 河南省 | | 8 | 200000 | 海南省 | | 9 | 200001 | 云南省 | | 10 | 200002 | 山西省 | | 16 | 3000 | 台湾省 | +----+--------+-----------+ #新增的数据没了,新增的表还在,
- 在db4.sheng新增一条记录
- 注意
- 恢复库时如果恢复到原库会将表中数据覆盖,新增表不会删除
- 数据恢复时如果恢复的库不存在,则必须先创建空库
8,MySQL的用户账户管理
- 开启MySQL远程连接
- sudo -i
- cd /etc/mysql/mysql.conf.d/
- subl mysqld.cnf
#bind-address = 127.0.0.1 (前面加#键)
ctrl+s保存 - /etc/init.d/mysql restart(重启)
- 添加授权用户
- mysql -uroot -p123456
- 授权
grant 授权列表 on 库.表,to '用户名'@'%'
identified by '密码' with grant option;
权限列表 : all privileges、select、insert
库.表 : *.* 所有库的所有表 - 示例
- 添加授权用户tiger,密码123,对所有库的所有表有所有权限
grant all privileges on *.* to 'tiger'@'%'
identified by '123' with grant option;
mysql -utiger -p123 - 添加用户rabbit,对db4库有所有权限
grant all privileges on db4.* to "rabbit"@"%" identified by "123" with grant option;
$ mysql -urabbit -p123 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db4 | +--------------------+ 2 rows in set (0.01 sec)
- 添加授权用户tiger,密码123,对所有库的所有表有所有权限
9,作业
- 综述:两张表,一张顾客信息表customers,一张订单表orders
-
创建一张顾客信息表customers,字段要求如下:
c_id 类型为整型,设置为主键,并设置为自增长属性
c_name 字符类型,变长,宽度为20
c_age 微小整型,取值范围为0~255(无符号)
c_sex 枚举类型,要求只能在('M','F')中选择一个值
c_city 字符类型,变长,宽度为20
c_salary 浮点类型,要求整数部分最大为10位,小数部分为2位
create table customers( c_id int primary key auto_increment, c_name varchar(20), c_age tinyint unsigned, c_sex enum('M','F'), c_city varchar(20), c_salary decimal(12,2) );
在表中任意插入3条记录,c_name为"Zhangsan","Lisi","Wangwu", c_city尽量 写"Beijing","Shanghai" ......
insert into customers values
(1,"Zhangsan",25,"M","Beijing",8000),
(2,"Lisi",30,"F","Shanghai",10000),
(3,"Wangwu",27,"M","Shenzhen",3000); -
创建一张订单表orders,字段要求如下:
o_id 整型
o_name 字符类型,变长,宽度为30
o_price 浮点类型,整数最大为10位,小数部分为2位
设置此表中的o_id字段为customers表中c_id字段的外键,更新删除同步
create table orders( o_id int, o_name varchar(30), o_price decimal(12,2), foreign key(o_id) references customers(c_id) on delete cascade on update cascade );
在表中任意插入5条记录(注意外键限制)
o_name分别为"iphone","ipad","iwatch","mate9","r11",其他信息自己定
insert into orders values
(1,"iphone",5288),
(1,"ipad",3299),
(3,"mate9",3688),
(2,"iwatch",2222),
(2,"r11",4400); -
返回customers表中,工资大于4000元,或者年龄小于29岁,满足这样条件的前2条记录
delect * from customers where c_salary > 4000 or c_age < 29 limit 2; -
把customers表中,年龄大于等于25岁,并且地址是北京或者上海,这样的人的工资上调15%
update customers set c_salary=c_salary*1.15 where c_age >= 25 and c_city in ("Beijing","Shanghai"); -
把customers表中,城市为北京的顾客,按照工资降序排列,并且只返回结果中的第一条记录
select * from customers
where c_city='Beijing'
order by c_salary desc limit 1; -
选择工资c_salary最少的顾客的信息
select * from customers
where c_salary = (select min(c_salary) from customers); -
找到工资大于5000的顾客都买过哪些产品的记录明细
select * from orders where o_id in (select c_id from customers where c_salary > 5000); -
删除外键限制
1、show create table orders;
2、alter table orders drop foreign key orders_ibfk_1;
-
删除customers主键限制
-
删除自增长属性
alter table customers modify c_id int; -
删除主键限制
alter table customers drop primary key;
-
-
增加customers主键限制c_id
alter table customers add primary key(c_id);
-