JavaWeb学习(三)之数据库

数据库

  • 约束
  • 数据库设计
  • 多表查询
  • 事务

1. 约束

  • 概念&分类
  • 非空约束
  • 唯一约束
  • 主键约束
  • 默认约束
  • 检查约束
  • 外键约束

 

  • 约束的概念和分类

1:约束的概念

  • 约束是作用于表中列上的规则,用于限制加入表的数据
  • 约束的存在保证了数据库中数据的正确性、有效性和完整性

2:约束的分类

约束名称 描述 关键字
非空约束 保证列中所有数据不能有null值 NOT NULL
唯一约束 保证列中所有数据各不相同 UNIQUE
主键约束 主键是一行数据的唯一标识,要求非空且唯一 PRIMARY KEY
检查约束 保证列中的值满足某一条件 CHECK
默认约束 保存数据时,未指定值则采用默认值 DEFAULT
外键约束 外键用来让两个表的数据之间建立链接,保证数据的唯一性和完整性 FOREIGN KEY

Tips:MySQL不支持检查约束

 
案例:根据需求,为表添加合适的约束(emp)

-- 员工表

CREATE TABLE emp (
	id INT, -- 员工id,主键且自增长
	ename VARCHAR(50), -- 员工姓名,非空且唯一
	joindate DATE, -- 入职日期,非空
	salary DOUBLE(7,2), -- 工资,非空
	bonus DOUBLE(7,2) -- 奖金,如果没有奖金默认为0
);
-- 员工表

create table emp (
	id int primary key auto_increment, -- 员工id,主键且自增长
	ename varchar(50) not null unique, -- 员工姓名,非空并且唯一
	joindate date not null, -- 入职日期,非空
	salary double(7,2) not null, -- 工资,非空
	bonus double(7,2) default 0 -- 奖金,如果没有奖金默认为0
	
);
  • 非空约束

1:概念

  • 非空约束用于保证列中所有数据不能有NULL值

2:语法

(1)添加约束

-- 创建表时添加非空约束

CREATE TABLE 表名(
	列名 数据类型 NOT NULL,);
-- 建完表后添加非空约束

ALTER TABLE 表名 MODIFY 字段名 数据类型 NOT NULL;

(2)删除约束

ALTER TABLE 表名 MODIFY 字段名 数据类型;
  • 唯一约束

1:概念

  • 唯一约束用于保证列中所有数据各不相同

2:语法

(1)添加约束

-- 创建表时添加唯一约束

CREATE TABLE 表名(
	列名 数据类型 UNIQUE [AUTO_INCREMENT],
	-- AUTO_INCREMENT:当不指定值时自动增长);


CREATE TABLE 表名(
	列名 数据类型,[CONSTRAINT] [约束名称] UNIQUE(列名)
);


-- 建完表后添加非空约束

ALTER TABLE 表名 MODIFY 字段名 数据类型 UNIQUE;

(2)删除约束

ALTER TABLE 表名 DROP INDEX 字段名;
  • 主键约束

1:概念

  • 主键是一行数据的唯一标识,要求非空且唯一
  • 一张表只能有一个主键

2:语法

(1)添加约束

-- 创建表时添加主键约束

CREATE TABLE 表名(
	列名 数据类型 PRIMARY KEY [AUTO_INCREMENT]);


CREATE TABLE 表名(
	列名 数据类型,
	[CONSTRAINT] [约束名称] PRIMARY KEY(列名)
);

 

-- 建完表后添加主键约束

ALTER TABLE 表名 ADD PRIMARY KEY(字段名);

(2)删除约束

ALTER TABLE 表名 DROP PRIMARY KEY;
  • 默认约束

1:概念

  • 保存数据时,未指定值则采用默认值

2:语法

(1)添加约束

-- 创建表时添加默认约束

CREATE TABLE 表名(
	列名 数据类型 DEFAULT 默认值,);


-- 建完表后添加默认约束

ALTER TABLE 表名 ALTER 列名 SET DEFAULT 默认值;

(2)删除约束

ALTER TABLE 表名 ALTER 列名 DROP DEFAULT;
  • 外键约束(emp、dept)

1:概念

  • 外键用来让两个表的数据之间建立链接,保证数据的一致性和完整性

emp 员工表

id name age dep_id
1 张三 20 1
2 李四 20 1
3 王五 20 1
4 赵六 20 2
5 孙七 22 2
6 周八 18 2

dept 部门表

id dep_name addr
1 研发部 广州
2 销售部 深圳

2:语法

(1)添加约束

-- 创建表时添加外键约束

CREATE TABLE 表名(
	列名 数据类型,[CONSTRAINT] [外键名称] FOREIGN KEY(外键列名) REFERENCES 主表(主表列名)
);
 

-- 建完表后添加外键约束

ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);

(2)删除约束

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

 


drop table if exists emp;

-- 员工表

create table emp (
	id int primary key auto_increment, -- 员工id,主键且自增长
	ename varchar(50) not null unique, -- 员工姓名,非空并且唯一
	joindate date not null, -- 入职日期,非空
	salary double(7,2) not null, -- 工资,非空
	bonus double(7,2) default 0 -- 奖金,如果没有奖金默认为0
	
);

select * from emp;

insert into emp(id,ename,joindate,salary,bonus) values(1,'张三','1999-11-11',8000,5000);

-- 演示主键约束:非空且唯一  (员工id)

insert into emp(id,ename,joindate,salary,bonus) values(null,'张三','1999-11-11',8000,5000);

insert into emp(id,ename,joindate,salary,bonus) values(1,'张三','1999-11-11',8000,5000);

insert into emp(id,ename,joindate,salary,bonus) values(2,'李四','1999-11-11',8000,5000);

-- 演示非空约束  (员工姓名)

insert into emp(id,ename,joindate,salary,bonus) values(3,null,'1999-11-11',8000,5000);

-- 演示唯一约束  (员工姓名)

insert into emp(id,ename,joindate,salary,bonus) values(3,'李四','1999-11-11',8000,5000);

-- 演示默认约束   (奖金)bonus也不要写了

delete from emp;
insert into emp(id,ename,joindate,salary) values(3,'王五','1999-11-11',8000);

insert into emp(id,ename,joindate,salary,bonus) values(4,'赵6','1999-11-11',8000,null);

-- 演示自动增长:auto_increment:当列是 数学类型 并且 唯一约束

insert into emp(ename,joindate,salary,bonus) values('赵6','1999-11-11',8800,null);

insert into emp(id,ename,joindate,salary,bonus) values(null,'赵62','1999-11-11',8800,null);

insert into emp(id,ename,joindate,salary,bonus) values(null,'赵63','1999-11-11',8800,null);

select * from emp;



drop table if exists dept;
drop table if exists emp;

-- 部门表
CREATE TABLE dept (
	did 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(did)
	
);


2. 数据库设计

  • 数据库设计简介
  • 表关系之一对多
  • 表关系之多对多
  • 表关系之一对一
  • 数据库设计案例

2.1 数据库设计简介

1:软件的研发步骤
JavaWeb学习(三)之数据库_第1张图片

2:数据库设计概念

  • 数据库设计就是根据业务系统的具体需求,结合我们所选用的DBMS,为这个业务系统构造出最优的数据存储模型。
  • 建立数据库中的表结构以及表与表之间的关联关系的过程
  • 有哪些表?表里有哪些字段?表和表之间有什么关系?

3:数据库设计的步骤

  • 需求分析(数据是什么?数据具有哪些属性?数据与属性的特点是什么)
  • 逻辑分析(通过ER图对数据库进行逻辑建模,不需要考虑我们所选用的数据库管理系统)
  • 物理设计(根据数据库自身的特点把逻辑设计转换为物理设计)
  • 维护设计(1.对新的需求进行建表;2.表优化)

4: 表关系

  • 一对多(多对一):

    • 如:部门 和 员工

    • 一个部门对应多个员工,一个员工对应一个部门

  • 多对多

    • 如:商品 和 订单

    • 一个商品对应多个订单,一个订单包含多个商品

  • 一对一:

    • 如:用户 和 用户详情

    • 一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能

2.2 表关系之一对多

  • 一对多(多对一):

    • 如:部门 和 员工

    • 一个部门对应多个员工,一个员工对应一个部门

  • 实现方式:在的一方建立外键,指向的一方的主键

tb_emp 员工表 M

id name age
1 张三 23
2 李四 24
3 王五 25

tb_dept 部门表 1

id name addr
1 财务部 北京
2 市场部 上海
3 研发部 成都

2.3 表关系之多对多

  • 多对多

如:订单 和 商品

一个商品对应多个订单,一个订单包含多个商品

  • 实现方式:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

tb_order 订单表 M

id payment payment_type status
1 7376.00 微信支付 未付款
2 59880.00 支付宝支付 已付款

tb_goods 商品表 M

id title price
1 华为P40手机 5988
2 海天酱油 9.9
3 华为GT2手表 1388

tb_order_goods 订单商品中间表

id order_id goods_id count
1 1 1 1
2 1 3 1
3 2 1 10
/*
	多对多:
		如:订单 和 商品
		一个商品对应多个订单,一个订单包含多个商品
		
	实现方式:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
	
*/


-- 删除表
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);


select * from tb_order;
select * from tb_goods;
select * from tb_order_goods;

2.4 表关系之一对一 表(tb_user、tb_user_desc) 查询(tb_user)

  • 一对一:

如:用户 和 用户详情

一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能

  • 实现方式:在任意一方加入外键,关联另一方主键,并且设置外键为唯一(UNIQUE)

tb_user 用户表

id photo nickname age gendar city edu income status desc
1 a.jpg 一场梦 23 广州 硕士 3000 单身
2 b.png 风清扬 35 湖北 本科 30000 离异
3 c.jpg 赵云 41 河南 本科 40000 单身

tb_user 用户表 1

id photo nickname age gendar desc_id
1 a.jpg 一场梦 23 1
2 b.png 风清扬 35 2
3 c.jpg 赵云 41 3

tb_user_desc 用户详情表 1

id city edu income status desc
1 广州 硕士 3000 单身
2 湖北 本科 30000 离异
3 河南 本科 40000 单身

drop table if exists tb_user;
drop table if exists tb_user_desc

select * from tb_user;
select * from tb_user_desc;


-- tb_user_desc 用户详情表
create table tb_user_desc (
	id int primary key auto_increment,
	city varchar(20) not null,
	edu varchar(20) not null,
	income double(7,2) default 0,
	status varchar(20),
	descc varchar(20)
);

-- tb_user 用户表
create table tb_user (
	id int primary key auto_increment,
	photo varchar(20) not null,
	nickname varchar(20) not null unique,
	age int not null,
	gendar varchar(20),
	desc_id int unique,
	
	constraint fk_user_desc foreign key(desc_id) references tb_user_desc(id)
	
);


-- tb_user 添加数据
insert into tb_user(id,photo,nickname,age,gendar) values
(1,'a.jpg','一场梦',23,'女'),
(2,'b.png','风清扬',35,'男'),
(3,'c.jpg','赵云',41,'男');


-- tb_user_desc 添加数据
insert into tb_user_desc(id,city,edu,income,statu,descs) values
(1,'广州','硕士',3000,'单身','...'),
(2,'湖北','本科',30000,'离异','...'),
(3,'河南','本科',40000,'单身','...');

2.5 数据库设计案例

JavaWeb学习(三)之数据库_第2张图片

3. 多表查询 查询(emp)

  • 多表查询简介
  • 内连接
  • 外连接
  • 子查询
  • 多表查询案例

1:多表查询简介

  • 笛卡尔积:取A,B集合的所有组合情况

  • 多表查询:从多张表查询数据

    • 连接查询:

      • 内连接:相当于查询A,B交集数据

      • 外连接:

        • 左外连接:相当于查询A表所有数据和交集部分数据

        • 右外连接:相当于查询B表所有数据和交集部分数据

    • 子查询

2:内连接

  • 内连接查询语法
-- 隐式内连接

SELECT 字段列表 FROM1,2WHERE 条件;
 

-- 显式内连接

SELECT 字段列表 FROM1 [INNER] JOIN2 ON 条件;

内连接相当于查询A B 交集数据

3:外连接

  • 外连接查询语法
-- 左外连接

SELECT 字段列表 FROM1 LEFT [OUTER] JOIN2 ON 条件;
 

-- 右外连接

SELECT 字段列表 FROM1 RIGHT [OUTER] JOIN2 ON 条件;
  • 左外连接:相当于查询A表所有数据和交集部分数据
  • 右外连接:相当于查询B表所有数据和交集部分数据

4:子查询

子查询概念:查询中嵌套查询,称嵌套查询为子查询

 
子查询根据查询结果不同,作用不同:

单行单列:作为条件值,使用 = != > < 等进行条件判断

SELECT 字段列表 FROMWHERE 字段名 = (子查询);

多行单列:作为条件值,使用in等关键字进行条件判断

SELECT 字段列表 FROMWHERE 字段名 in (子查询);

多行多列:作为虚拟表

SELECT 字段列表 FROM (子查询) WHERE 条件;

 

drop table if exists dept;
drop table if exists emp;

-- 部门表
CREATE TABLE dept (
	did 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(did)
	
);

-- 添加两个部门

insert into dept(did,dep_name,addr) values(1,'研发部','广州'),(2,'销售部','深圳'),(3,'市场部','北京');

-- 添加员工,dep_id 表示员工所在的部门
insert into emp(id,name,age,dep_id) values
(1,'张三',20,1),
(2,'李四',20,1),
(3,'王五',20,1),
(4,'赵六',20,2),
(5,'孙七',22,2),
(6,'周八',18,2),
(7,'阿九',18,null);

-- -------------------------


select * from emp;
select * from dept;



-- 删除外键

alter table emp drop foreign key fk_emp_dept;


-- 建完表之后添加外键  

alter table emp add constraint fk_emp_dept foreign key(dep_id) references dept(did);




-- 多表查询

select * from emp , dept;

-- 笛卡尔积:有 A,B两个集合,取A,B所有的组合情况


-- 消除无效数据

-- 查询emp 和 dept 的数据,emp.dep_id = dep.id
-- 隐式内连接
select * from emp , dept where emp.dep_id = dept.did;

-- 查询 emp 的 name , gender , dept 表的 dep_name
select emp.name,emp.age,dept.dep_name from emp , dept where emp.dep_id = dept.did;

-- 给表起别名
select t1.name,t1.age,t2.dep_name 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;




-- 外连接

select * from emp;
select * from dept;

-- 左外连接
-- 查询emp表所有数据和对应的部门信息
select * from emp left outer join dept on emp.dep_id = dept.did;

-- 右外连接
-- 查询dept表所有数据和对应的员工信息
select * from emp right outer join dept on emp.dep_id = dept.did;

select * from dept left outer join emp on emp.dep_id = dept.did;  -- 左外连接也可做右外连接的事,把两个表名换过来就可以了


-- 嵌套查询
-- 查询年龄大于张三的员工信息

select * from emp;
select * from dept;

-- 1.查询张三的年龄
select age from emp where name = '张三';

-- 2.查询年龄高于张三的员工信息

select * from emp where age > 20;

-- 单行单列
select * from emp where age > (select age from emp where name = '张三');

-- 多行单列
-- 查询 '研发部' 和 '销售部'所有员工信息
select did from dept where dep_name = '研发部' or dep_name = '销售部';
select * from emp where dep_id in (1,2);
select * from emp where dep_id in (select did from dept where dep_name = '研发部' or dep_name = '销售部');

-- 查询 '研发部'的员工信息
select did from dept where dep_name = '研发部';
select * from emp where dep_id = 1;
select * from emp where dep_id = (select did from dept where dep_name = '研发部');


-- 多行多列
-- 查询年龄大于19岁的员工信息和部门信息

-- 查询年龄大于19岁的员工的员工信息
select * from emp where age > 19;

select * from (select * from emp where age > 19) t1, dept where t1.dep_id = dept.did;

5:多表查询案例 表(emp1、dept1、job、salarygrade)查询(job)

drop table if exists emp1;
drop table if exists dept1;
drop table if exists job;
drop table if exists salarygrade;


-- 部门表
create table dept1 (
	id int primary key primary key, -- 部门id
	dname varchar(50), -- 部门名称
	loc varchar(50) -- 部门所在地
);


-- 职务表,职务名称,职务描述
create table job (
	id int primary key, -- 员工id
	jname varchar(20),
	description varchar(50)
);


-- 员工表
create table emp1 (
	id int primary key, -- 员工id
	ename varchar(50), -- 员工姓名
	job_id int, -- 职务id
	mgr int, -- 上级领导
	joindate date, -- 入职日期
	salary decimal(7,2), -- 工资 
	bonus decimal(7,2), -- 奖金
	dept1_id int, -- 所在部门编号
	constraint emp1_jobid_ref_job_id_fk foreign key (job_id) references job (id),
	constraint emp1_deptid_ref_dept1_id_fk foreign key (dept1_id) references dept1 (id)
);


-- 工资等级表
create table salarygrade (
	grade int primary key, -- 级别
	losalary int, -- 最低工资
	hisalary int -- 最高工资
);



-- 添加4个部门
insert into dept1(id,dname,loc) values
(10,'教研部','北京'),
(20,'学工部','上海'),
(30,'销售部','广州'),
(40,'账务部','深圳');


-- 添加4个职务
insert into job (id,jname,description) values
(1,'董事长','管理整个公司,接单'),
(2,'经理','管理部门员工'),
(3,'销售员','向客人推销产品'),
(4,'文员','使用办公软件');


-- 添加员工
insert into emp1(id,ename,job_id,mgr,joindate,salary,bonus,dept1_id) values
(1001,'孙悟空',4,1004,'2002-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','25800.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);



select * from emp1;
select * from dept1;
select * from job;
select * from salarygrade;


-- 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职称描述
/*
	分析:
	1.员工编号,员工姓名,工资 信息在 empq 员工表中
	2.职务名称,职务描述 信息在 job 职务表中
	3.job 职务表 和 emp1 员工表 是 一双多的关系 emp1.job_id = job.id
*/

-- 隐式内连接
select emp1.id, emp1.ename, emp1.salary, job.jname, job.description from emp1 , job where emp1.job_id = job.id;

select * from emp1;
select * from job;

-- 显式内连接
select emp1.id, emp1.ename, emp1.salary, job.jname, job.description from emp1 inner join job on emp1.job_id = job.id;

-- 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
/*
	分析:
	1.员工编号,员工姓名,工资 信息在 empq 员工表中
	2.职务名称,职务描述 信息在 job 职务表中
	3.job 职务表 和 emp1 员工表 是 一对多的关系 emp1.job_id = job.id
	
	4.部门名称,部门位置 来自于 部门表 dept1
	5.dept1 和 emp1 一对多的关系  dept1.id = emp.dept_id
*/

-- 隐式内连接
SELECT
	emp1.id,
	emp1.ename,
	emp1.salary,
	job.jname,
	job.description,
	dept1.dname,
	dept1.loc
FROM
	emp1,
	job,
	dept1 
WHERE
	emp1.job_id = job.id 
	AND emp1.dept1_id = dept1.id;

select * from emp1;
select * from job;
select * from dept1;

-- 显式内连接
SELECT
	emp1.id,
	emp1.ename,
	emp1.salary,
	job.jname,
	job.description,
	dept1.dname,
	dept1.loc
FROM
	emp1
	INNER JOIN job ON emp1.job_id = job.id
	inner join dept1 on emp1.dept1_id = dept1.id;

-- 3.查询员工姓名,工资,工资等级
/*
	分析:
	1.员工姓名,工资 信息在 emp1 员工表中
	2.工资等级 信息在 salarygrade 工资等级表
	3.emp1.salary >= salarygrade.losalary and emp1.salary <= salagrade.hisalary
*/
select emp1.ename, emp1.salary, t2.grade from emp1, salarygrade t2 where emp1.salary >= t2.losalary and emp1.salary <= t2.hisalary;
select emp1.ename, emp1.salary, t2.* from emp1, salarygrade t2 where emp1.salary >= t2.losalary and emp1.salary <= t2.hisalary;
select emp1.ename, emp1.salary, t2.grade from emp1, salarygrade t2 where emp1.salary between t2.losalary and t2.hisalary;


-- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
/*
分析:
	1.员工姓名,工资 信息在 emp1 员工表中
	2.职务名称,职务描述 信息在 job 职务表中
	3.job 职务表 和 emp1 员工表 是 一对多的关系 emp1.job_id = job.id
	
	4.部门名称,部门位置 来自于 部门表 dept1
	5.dept1 和 emp1 一对多的关系  dept1.id = emp.dept_id
	6.工资等级 信息在 salarygrade 工资等级表
	7.emp1.salary >= salarygrade.losalary and emp1.salary <= salagrade.hisalary
*/

SELECT
	emp1.id,
	emp1.ename,
	emp1.salary,
	job.jname,
	job.description,
	dept1.dname,
	dept1.loc,
	t2.grade 
FROM
	emp1
	INNER JOIN job ON emp1.job_id = job.id
	INNER JOIN dept1 ON emp1.dept1_id = dept1.id
	INNER JOIN salarygrade t2 ON emp1.salary BETWEEN t2.losalary 
	AND t2.hisalary;

-- 5.查询出部门编号,部门名称,部门位置,部门人数
/*
分析:
	1.部门编号、部门名称、部门位置 来自于部门 dept 表
	2.部门人数:在emp1表中 按照dept1_id 进行分组,然后count(*)统计数据
	3.使用子查询,让部门表和分组后的表进行内连接
*/

select * from dept1;

select dept1_id, count(*) from emp1 group by dept1_id ;

SELECT
	dept1.id,
	dept1.dname,
	dept1.loc,
	t1.count 
FROM
	dept1,(
	SELECT
		dept1_id,
		count(*) count 
	FROM
		emp1 
	GROUP BY
		dept1_id 
	) t1 
WHERE
	dept1.id = t1.dept1_id;

4. 事务

  • 事务简介
  • 事务操作
  • 事务四大特征

1:事务简介

  • 数据库的事务(Transaction)是一种机制、一种操作序列,包含了一组数据库操作命令
  • 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么同时成功,要么同时失败
  • 事务是一个不可分割的工作逻辑单元
id name money
1 张三 1000
2 李四 1000

例子:张三向李四借500元,一个表记录,张三、李四的钱,两个各1000,怎么完成转账的操作呢,

查询李四帐户余额

李四帐户余额-500

张三帐户余额+500

出现异常,李四-500,张三余额没有+500,这种操作明显不合理,怎么预防这个问题呢

就要用到今天学的 事务 了。事务是一组命令,要么同时成功,要么同时失败,金钱总数不变

转账操作之前,开启事务,执行成功之后,提交事务,出现异常,则回滚事务

开启事务就是打一个标记,告诉数据库,这后面的执行是一些临时更改,例如说,给李四账户-500,它不真正的去把你整个数据库改了,它是一个临时的修改,

只有当你遇到了提交事务之后,才会真正的持久化的把这个表的数据改掉,

那么将来但凡有哪个地方呢,出现了异常,它就回滚事务,回滚事务就是撤销之前的临时操作,回滚到你开启事务之前的那个状态,

也就是张三,李四两个人的金钱不变的那个状态

2:事务操作表(account) 查询(account、anotheraccount)

-- 开启事务

START TRANSACTION;

或者 BEGIN;
 

-- 提交事务

COMMIT;
 

-- 回滚事务

ROLLBACK;

3:事务四大特征(非常常见的一个面试题)

  • 原子性(Atomicity):事务是不可分割的最小操作单位,要么同时成功,要么同时失败
  • 一致性(Consisterncy):事务完成时,必须使所有的数据都保持一致状态 (金钱总额保持不变)
  • 隔离性(Isolation):多个事务之间,操作的可见性

(两个窗口,两个窗口其实就是对应着将来的两个事务,那么这两个事务之间的数据是否操作可见,那么就是我们据说的隔离性。隔离性越强,那么操作越不可见的,那么它的性能也就越低。一般不改变隔离性,用默认的,默认的就是我们在MySQL里边,当别人提交了或者回滚了,我才能看到对应对方的一个修改)

  • 持久性(Durability):事务一旦提交或回滚,它对数据库中数据的改变就是永久的

(也就是意味着在事务操作的过程中开启了事务,操作的过程中都是一些临时的改变,那么只有当你提交或者回滚才会真正的把这个操作的数据给它写到硬盘的文件上,落盘了之后持久化)

MySQL事务默认自动提交

-- 查看事务的默认提交方式

SELECT @@autocommit;

-- 1 自动提交 0 手动提交

set @@autocommit = 0;

将来用来Oracle,它的事务默认是手动提交的,也就是意味着将来你在写Oracle的SQL的时候,你一定记得commit提交,如果不提交,将来这个窗口一关,这个SQL其实不会被修改生效的。

在MySQL中,开启事务后面的其实也是要自己手动提交


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);

select * from account;


select * from account;
update account set money = 1000;

-- 转账操作
 
-- 开启事务
begin;  -- 开启这个事务后,数据会临时更改,在当前这个用户会更改,在anotheraccount用户中查询不会更改
-- start transaction;

-- 1.查询李四的余额
-- select money from account where name = '李四';

-- 2.把李四的帐户 -500
update account set money = money - 500 where name = '李四';

-- 模拟异常
-- 出错了...

-- 3.把张三的帐户 +500
update account set money = money + 500 where name = '张三'
-- select money from account where name = '张三';

-- 提交事务
commit;

-- 回滚事务
rollback;  -- 执行一下,回滚事务就相当于回滚到开启事务之前的这个状态

select * from account;


-- 1.查询事务的默认提交方式
select @@autocommit;
-- 1 自动提交  0  手动提交
-- 修改事务的提交方式,改为手动提交
set @@autocommit = 0;
set @@autocommit = 1;

-- 2.把李四的帐户 -500
update account set money = money - 500 where name = '李四';
-- 1 默认为事务自动提交,也就是做了一个操作之后,在其他窗口查也是一样的结果,就相当于操作后面写了一个 commit 
-- 0 默认为事务手动提交,了就是做了一个操作之后,其实做了一个临时的更改,在这个窗口临时改了,在其它窗口没有更改,因为没有commit提交事务
-- commit
commit;


select * from account;

update account set money = 2000 where id = 1;

你可能感兴趣的:(JavaWeb,数据库,学习,java)