mysql高级

1,约束

1.1 概念 

 1.2 分类

外键约束

概述

 语法

* 添加外键约束

```sql
-- 创建表时添加外键约束
CREATE TABLE 表名(
   列名 数据类型,
   …
   [CONSTRAINT] [外键名称] FOREIGN KEY(外键列名) REFERENCES 主表(主表列名)
);
```

```sql
-- 建完表后添加外键约束
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
```

* 删除外键约束

```sql
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
```

1.8.3 练习

-- 删除表
DROP TABLE IF EXISTS emp;
DROP TABLE IF EXISTS dept;

-- 部门表
CREATE TABLE dept(
    id int primary key auto_increment,
    dep_name varchar(20),
    addr varchar(20)
);
-- 员工表
CREATE TABLE emp(
    id int primary key auto_increment,
    name varchar(20),
    age int,
    dep_id int,

    -- 添加外键 dep_id,关联 dept 表的id主键
    CONSTRAINT fk_emp_dept FOREIGN KEY(dep_id) REFERENCES dept(id)    
);

-- 添加 2 个部门
insert into dept(dep_name,addr) values
('研发部','广州'),('销售部', '深圳');

-- 添加员工,dep_id 表示员工所在的部门
INSERT INTO emp (NAME, age, dep_id) VALUES
('张三', 20, 1),
('李四', 20, 1),
('王五', 20, 1),
('赵六', 20, 2),
('孙七', 22, 2),
('周八', 18, 2);

 

删除外键

```sql
alter table emp drop FOREIGN key fk_emp_dept;
```

重新添加外键

```sql
alter table emp add CONSTRAINT fk_emp_dept FOREIGN key(dep_id) REFERENCES dept(id);

2,数据库设计 

2.1 数据库设计简介

 

 

 

 2.2 表关系(一对多)

2.3 表关系(多对多) 

 

 -- 删除表
  DROP TABLE IF EXISTS tb_order_goods;
  DROP TABLE IF EXISTS tb_order;
  DROP TABLE IF EXISTS tb_goods;
 
  -- 订单表
  CREATE TABLE tb_order(
      id int primary key auto_increment,
      payment double(10,2),
      payment_type TINYINT,
      status TINYINT
  );
 
  -- 商品表
  CREATE TABLE tb_goods(
      id int primary key auto_increment,
      title varchar(100),
      price double(10,2)
  );
 
  -- 订单商品中间表
  CREATE TABLE tb_order_goods(
      id int primary key auto_increment,
      order_id int,
      goods_id int,
      count int
  );
 
  -- 建完表后,添加外键
  alter table tb_order_goods add CONSTRAINT fk_order_id FOREIGN key(order_id) REFERENCES tb_order(id);
  alter table tb_order_goods add CONSTRAINT fk_goods_id FOREIGN key(goods_id) REFERENCES tb_goods(id);
  ```

 

 2.4 表关系(一对一)

 

 

create table tb_user_desc (
    id int primary key auto_increment,
    city varchar(20),
    edu varchar(10),
    income int,
    status char(2),
    des varchar(100)
);

create table tb_user (
    id int primary key auto_increment,
    photo varchar(100),
    nickname varchar(50),
    age int,
    gender char(1),
    desc_id int unique,
    -- 添加外键
    CONSTRAINT fk_user_desc FOREIGN KEY(desc_id) REFERENCES tb_user_desc(id)    
);

2.5 数据库设计案例

根据下图设计表及表和表之间的关系:

经过分析,我们分为 专辑表 曲目表 短评表 用户表 4张表。

 3,多表查询

 

DROP TABLE IF EXISTS emp;
DROP TABLE IF EXISTS dept;


# 创建部门表
    CREATE TABLE dept(
        did INT PRIMARY KEY AUTO_INCREMENT,
        dname VARCHAR(20)
    );

    # 创建员工表
    CREATE TABLE emp (
        id INT PRIMARY KEY AUTO_INCREMENT,
        NAME VARCHAR(10),
        gender CHAR(1), -- 性别
        salary DOUBLE, -- 工资
        join_date DATE, -- 入职日期
        dep_id INT,
        FOREIGN KEY (dep_id) REFERENCES dept(did) -- 外键,关联部门表(部门表的主键)
    );
    -- 添加部门数据
    INSERT INTO dept (dNAME) VALUES ('研发部'),('市场部'),('财务部'),('销售部');
    -- 添加员工数据
    INSERT INTO emp(NAME,gender,salary,join_date,dep_id) VALUES
    ('孙悟空','男',7200,'2013-02-24',1),
    ('猪八戒','男',3600,'2010-12-02',2),
    ('唐僧','男',9000,'2008-08-08',2),
    ('白骨精','女',5000,'2015-10-07',3),
    ('蜘蛛精','女',4500,'2011-03-14',1),
    ('小白龙','男',2500,'2011-02-14',null);

 select * from emp , dept;  -- 从emp和dept表中查询所有的字段数据

 select * from emp , dept where emp.dep_id = dept.did;

 

左连接:A  和A∩B这块;

右连接:B  和A∩B这块;

内连接查询

语法

案例  

隐式内连接

     SELECT
        *
    FROM
        emp,
        dept
    WHERE
        emp.dep_id = dept.did;

 

 SELECT
        emp. NAME,
        emp.gender,
        dept.dname
    FROM
        emp,
        dept
    WHERE
        emp.dep_id = dept.did;

上面语句中使用表名指定字段所属有点麻烦, sql 也支持给表指别名,上述语句可以改进为

 SELECT
        t1. NAME,
        t1.gender,
        t2.dname
    FROM
        emp t1,
        dept t2
    WHERE
        t1.dep_id = t2.did;、

显式内连接

   select * from emp inner join dept on emp.dep_id = dept.did;
    -- 上面语句中的inner可以省略,可以书写为如下语句
    select * from emp  join dept on emp.dep_id = dept.did;

3.2 外连接查询

 案例

 select * from emp left join dept on emp.dep_id = dept.did;

查询dept表所有数据和对应的员工信息(右外连接) 

SELECT * FROM emp RIGHT JOIN dept on emp.dep_id = dept.did;

结果显示查询到了右表( dept )中所有的数据及两张表能关联的数据。
要查询出部门表中所有的数据, 也可以通过左外连接实现,只需要将两个表的位置进行互换

select * from dept left join emp on emp.dep_id = dept.did;  

3.3 子查询  

概念
查询中嵌套查询,称嵌套查询为子查询。
什么是查询中嵌套查询呢?我们通过一个例子来看:
需求:查询工资高于猪八戒的员工信息。
来实现这个需求,我们就可以通过二步实现,
第一步:先查询出来 猪八戒的工资

select salary from emp where name = '猪八戒'

第二步:查询工资高于猪八戒的员工信息  

select * from emp where salary > 3600 ;

第三步中的 3600 可以通过第一步的 sql 查询出来,所以将 3600 用第一步的 sql 语句进行替换

 select * from emp where salary > (select salary from emp where name = '猪八戒');

这就是查询语句中嵌套查询语句。
子查询根据查询结果不同,作用不同

子查询语句结果是单行单列,子查询语句作为条件值,使用 = != > < 等进行条件判断
子查询语句结果是多行单列,子查询语句作为条件值,使用 in 等关键字进行条件判断
子查询语句结果是多行多列,子查询语句作为虚拟表

案例

查询 ' 财务部 ' ' 市场部 ' 所有的员工信息

  -- 查询 '财务部' 或者 '市场部' 所有的员工的部门did
    select did from dept where dname = '财务部' or dname = '市场部';
    
    select * from emp where dep_id in (select did from dept where dname = '财务部' or dname = '市场部');

 

案例二

查询入职日期是 '2011-11-11' 之后的员工信息和部门信息

  --  (第一步) 查询入职日期是 '2011-11-11' 之后的员工信息
select * from emp where join_date > '2011-11-11' ;

-- (第二步)将上面语句的结果作为虚拟表和dept表进行内连接查询

SELECT * FROM(select * from emp where join_date > '2011-11-11') t1,dept where t1.dep_id = dept.did;

 3.4 案例

环境准备:
DROP TABLE IF EXISTS emp;
DROP TABLE IF EXISTS dept;
DROP TABLE IF EXISTS job;
DROP TABLE IF EXISTS salarygrade;
-- 部门表
CREATE TABLE dept (
did INT PRIMARY KEY PRIMARY KEY , -- 部门 id
dname VARCHAR ( 50 ) , -- 部门名称
loc VARCHAR ( 50 ) -- 部门所在地
) ;
-- 职务表,职务名称,职务描述
CREATE TABLE job (
id INT PRIMARY KEY ,
jname VARCHAR ( 20 ) ,
description VARCHAR ( 50 )
) ;
-- 员工表
CREATE TABLE emp (
id INT PRIMARY KEY , -- 员工 id
ename VARCHAR ( 50 ) , -- 员工姓名
job_id INT , -- 职务 id
mgr INT , -- 上级领导
joindate DATE , -- 入职日期
salary DECIMAL ( 7 , 2 ) , -- 工资
bonus DECIMAL ( 7 , 2 ) , -- 奖金
dept_id INT , -- 所在部门编号
CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY ( job_id ) REFERENCES job ( id ) ,
CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY ( dept_id ) REFERENCES dept ( did )
) ;
-- 工资等级表
CREATE TABLE salarygrade (
grade INT PRIMARY KEY , -- 级别
losalary INT , -- 最低工资
hisalary INT -- 最高工资
) ;
-- 添加 4 个部门
INSERT INTO dept ( did,dname,loc ) VALUES
( 10 , ' 教研部 ' , ' 北京 ' ) ,
( 20 , ' 学工部 ' , ' 上海 ' ) ,
( 30 , ' 销售部 ' , ' 广州 ' ) ,
( 40 , ' 财务部 ' , ' 深圳 ' ) ;
-- 添加 4 个职务
INSERT INTO job ( id, jname, description ) VALUES
( 1 , ' 董事长 ' , ' 管理整个公司,接单 ' ) ,
( 2 , ' 经理 ' , ' 管理部门员工 ' ) ,
( 3 , ' 销售员 ' , ' 向客人推销产品 ' ) ,
( 4 , ' 文员 ' , ' 使用办公软件 ' ) ;
-- 添加员工
INSERT INTO emp ( id,ename,job_id,mgr,joindate,salary,bonus,dept_id ) VALUES
( 1001 , ' 孙悟空 ' , 4 , 1004 , '2000-12-17' , '8000.00' , NULL , 20 ) ,
( 1002 , ' 卢俊义 ' , 3 , 1006 , '2001-02-20' , '16000.00' , '3000.00' , 30 ) ,
( 1003 , ' 林冲 ' , 3 , 1006 , '2001-02-22' , '12500.00' , '5000.00' , 30 ) ,
( 1004 , ' 唐僧 ' , 2 , 1009 , '2001-04-02' , '29750.00' , NULL , 20 ) ,
( 1005 , ' 李逵 ' , 4 , 1006 , '2001-09-28' , '12500.00' , '14000.00' , 30 ) ,
( 1006 , ' 宋江 ' , 2 , 1009 , '2001-05-01' , '28500.00' , NULL , 30 ) ,
( 1007 , ' 刘备 ' , 2 , 1009 , '2001-09-01' , '24500.00' , NULL , 10 ) ,
( 1008 , ' 猪八戒 ' , 4 , 1004 , '2007-04-19' , '30000.00' , NULL , 20 ) ,
( 1009 , ' 罗贯中 ' , 1 , NULL , '2001-11-17' , '50000.00' , NULL , 10 ) ,
( 1010 , ' 吴用 ' , 3 , 1006 , '2001-09-08' , '15000.00' , '0.00' , 30 ) ,
( 1011 , ' 沙僧 ' , 4 , 1004 , '2007-05-23' , '11000.00' , NULL , 20 ) ,
( 1012 , ' 李逵 ' , 4 , 1006 , '2001-12-03' , '9500.00' , NULL , 30 ) ,
( 1013 , ' 小白龙 ' , 4 , 1004 , '2001-12-03' , '30000.00' , NULL , 20 ) ,
( 1014 , ' 关羽 ' , 4 , 1007 , '2002-01-23' , '13000.00' , NULL , 10 ) ;
-- 添加 5 个工资等级
INSERT INTO salarygrade ( grade,losalary,hisalary ) VALUES
( 1 , 7000 , 12000 ) ,
( 2 , 12010 , 14000 ) ,
( 3 , 14010 , 20000 ) ,
( 4 , 20010 , 30000 ) ,
( 5 , 30010 , 99990 ) ;

需求

1. 查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述

/*
分析:
1. 员工编号,员工姓名,工资 信息在 emp 员工表中
2. 职务名称,职务描述 信息在 job 职务表中
3. job 职务表 和 emp 员工表 是 一对多的关系 emp.job_id = job.id
*/
-- 方式一 :隐式内连接
SELECT
emp .id ,
emp .ename ,
emp .salary ,
job .jname ,
job .description
FROM
emp,
job
WHERE
emp .job_id = job .id ;

-- 方式二 :显式内连接
SELECT
emp .id ,
emp .ename ,
emp .salary ,
job .jname ,
job .description
FROM
emp
INNER JOIN job ON emp .job_id = job .id ;
2. 查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
/*
分析:
1. 员工编号,员工姓名,工资 信息在 emp 员工表中
2. 职务名称,职务描述 信息在 job 职务表中
3. job 职务表 和 emp 员工表 是 一对多的关系 emp.job_id = job.id
4. 部门名称,部门位置 来自于 部门表 dept
5. dept emp 一对多关系 dept.id = emp.dept_id
*/
-- 方式一 :隐式内连接
SELECT
emp .id ,
emp .ename ,
emp .salary ,
job .jname ,
job .description ,
dept .dname ,
dept .loc
FROM
emp,
job,
dept
WHERE
emp .job_id = job .id
and dept .id = emp .dept_id ;

-- 方式二 :显式内连接
SELECT
emp .id ,
emp .ename ,
emp .salary ,
job .jname ,
job .description ,
dept .dname ,
dept .loc
FROM
emp
INNER JOIN job ON emp .job_id = job .id
INNER JOIN dept ON dept .id = emp .dept_id
3. 查询员工姓名,工资,工资等级
/*
分析:
1. 员工姓名,工资 信息在 emp 员工表中
2. 工资等级 信息在 salarygrade 工资等级表中
3. emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
*/
完整版
SELECT
emp.ename,
emp.salary,
salarygrade.grade,
salarygrade.losalary,
salarygrade.hisalary
FROM emp,salarygrade
WHERE emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
简略版(改名)
SELECT
emp .ename ,
emp .salary ,
t2. *
FROM
emp,
salarygrade t2
WHERE
emp .salary >= t2 .losalary
AND emp .salary <= t2 .hisalary
4. 查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级 (跳过)
/*
分析:
1. 员工编号,员工姓名,工资 信息在 emp 员工表中
2. 职务名称,职务描述 信息在 job 职务表中
3. job 职务表 和 emp 员工表 是 一对多的关系 emp.job_id = job.id
4. 部门名称,部门位置 来自于 部门表 dept
5. dept emp 一对多关系 dept.id = emp.dept_id
6. 工资等级 信息在 salarygrade 工资等级表中
7. emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
*/
SELECT
        emp .id ,
        emp .ename ,
        emp .salary ,
        job .jname ,
        job .description ,
        dept .dname ,
        dept .loc ,
        t2 .grade
FROM
        emp
INNER JOIN job ON emp .job_id = job .id
INNER JOIN dept ON dept .did = emp .dept_id
INNER JOIN salarygrade t2 ON emp .salary BETWEEN t2 .losalary and t2 .hisalary ;

5. 查询出部门编号、部门名称、部门位置、部门人数 (跳过)
/*
分析:
1. 部门编号、部门名称、部门位置 来自于部门 dept
2. 部门人数 : emp 表中 按照 dept_id 进行分组,然后 count(*) 统计数量
3. 使用子查询,让部门表和分组后的表进行内连接
*/
-- 根据部门 id 分组查询每一个部门 id 和员工数
select dept_id, count ( * ) from emp group by dept_id;
SELECT
dept .id ,
dept .dname ,
dept .loc ,
t1 .count
FROM
dept,
(
SELECT
dept_id,
count ( * ) count
FROM
emp
GROUP BY
dept_id
) t1
WHERE
dept .id = t1 .dept_id

4,事务

4.1 概述

 

 

 4.2 语法

 4.3 代码验证

 环境准备

DROP TABLE IF EXISTS account;
-- 创建账户表
CREATE TABLE account (
id int PRIMARY KEY auto_increment ,
name varchar ( 10 ) ,
money double ( 10 , 2 )
) ;
-- 添加数据
INSERT INTO account ( name,money ) values ( ' 张三 ' , 1000 ) , ( ' 李四 ' , 1000 ) ;
不加事务演示问题
-- 转账操作
-- 1. 查询李四账户金额是否大于 500
-- 2. 李四账户 -500
UPDATE account set money = money - 500 where name = ' 李四 ' ;
出现异常了 ... -- 此处不是注释,在整体执行时会出问题,后面的 sql 则不执行
-- 3. 张三账户 +500
UPDATE account set money = money + 500 where name = ' 张三 ' ;

 在新的查询表里查找还是一样的结果。

添加事务 sql 如下:
-- 开启事务
BEGIN ;
-- 转账操作
-- 1. 查询李四账户金额是否大于 500
-- 2. 李四账户 -500
UPDATE account set money = money - 500 where name = ' 李四 ' ;
出现异常了 ... -- 此处不是注释,在整体执行时会出问题,后面的 sql 则不执行
-- 3. 张三账户 +500
UPDATE account set money = money + 500 where name = ' 张三 ' ;
-- 提交事务
COMMIT ;
-- 回滚事务
ROLLBACK ;
(添加了begin出现异常,只在 当前查询表出错,新的查询表查询还是2000元)
回滚类似撤回
上面 sql 中的执行成功进选择执行提交事务,而出现问题则执行回滚事务的语句。以后我们肯定不可能这样操作,而是在java 中进行操作,在 java 中可以抓取异常,没出现异常提交事务,出现异常回滚事务。

4.4 事务的四大特征

面试题常问四大特征(ACIE)

原子性( A tomicity : 事务是不可分割的最小操作单位,要么同时成功,要么同时失败
一致性( C onsistency : 事务完成时,必须使所有的数据都保持一致状态
隔离性( I solation : 多个事务之间,操作的可见性
持久性( D urability : 事务一旦提交或回滚,它对数据库中的数据的改变就是永久的
说明:
mysql 中事务是自动提交的。
也就是说我们不添加事务执行 sql 语句,语句执行完毕会自动的提交事务。
可以通过下面语句查询默认提交方式:
SELECT @@autocommit ;
查询到的结果是 1 则表示自动提交,结果是 0 表示手动提交。当然也可以通过下面语句修改提交方式
set @@autocommit = 0 ;
Oracle数据库是需要手动提交事务;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值