数据库三大范式,多表关系;多表查询,数据库事务以及隔离级别;引入JDBC;JDBC操作DDL,DML语句
1.多表关系以及数据库的三大范式(设计层面:记忆) :理论
数据库的范式:是设计数据库一种规范要求,每一个范式呈递次规范;
第一范式1NF:数据库表中每一列是不可在拆分的原子性,不能出现复合列!(集合数据)
第二范式2NF:在1NF基础上,每一张表描述一件事情;非主键字段完全依赖于主键字段;
第三范式3NF:在2NF基础上,非主键字段和主键字段不能产生传递依赖,使用外键约束来操作
第一范式(1NF):列不可再分
1.每一列属性都是不可再分的属性值,确保每一列的原子性
2.两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据
举例:地址可以拆分为:字段省,市,县 第二范式(2NF):属性完全依赖于主键
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。
为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。
这个惟一属性列被称为主键
第三范式: 数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系。
像:a-->b-->c 属性之间含有这样的关系,是不符合第三范式的。
举例:比如Student表(学号,姓名,年龄,性别,所在院校,院校地址,院校电话)
这样一个表结构,就存在上述关系。 学号--> 所在院校 --> (院校地址,院校电话)
这样的表结构,我们应该拆开来,如下。
(学号,姓名,年龄,性别,所在院校)--(所在院校,院校地址,院校电话)
2.多表查询 (重点掌握)
1、操作步骤:
1)需要几张表(表名是什么)
2)查询指定表的中那些字段
3)这些表之间的关联关系是什么
内连接 inner可以不写
隐式内连接
SELECT 字段名 FROM 左表, 右表 WHERE 条件
select * from emp,dept where emp.`dept_id` = dept.`id`;
显式内连接
SELECT 字段名 FROM 左表 INNER JOIN 右表 ON 条件
select * from emp e inner join dept d on e.`dept_id` = d.`id`;
员工表.name='唐僧'
select * from emp e inner join dept d on e.`dept_id` = d.`id` where e.`name`='唐僧';
外连接 outer可以不写
左外连接
SELECT 字段名 FROM 左表 LEFT [OUTER] JOIN 右表 ON 条件
右外连接
SELECT 字段名 FROM 左表 RIGHT [OUTER ]JOIN 右表 ON 条件
子查询的概念:
1).一个查询的结果做为另一个查询的条件
2).有查询的嵌套,内部的查询称为子查询
3).子查询要使用括号
子查询结果的三种情况:
1),子查询的结果是单行单列
2),子查询的结果是多行单列
3),子查询的结果是多行多列
1.子查询的结果是一个值的时候
子查询结果只要是单行单列,肯定在 WHERE 后面作为条件,父查询使用:比较运算符,如:>、<、<>、= 等
SELECT 查询字段 FROM 表 WHERE 字段=(子查询);
案例:查询工资最高的员工是谁?
– 1) 查询最高工资是多少
select max(salary) from emp;
– 2) 根据最高工资到员工表查询到对应的员工信息
select * from emp where salary = (select max(salary) from emp);
查询工资小于平均工资的员工有哪些?
– 1) 查询平均工资是多少
select avg(salary) from emp;
– 2) 到员工表查询小于平均的员工信息
select * from emp where salary < (select avg(salary) from emp);
2.子查询结果是多行单列的时候
子查询结果是单例多行,结果集类似于一个数组,父查询使用 IN 运算符
SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);
案例: 查询工资大于 5000 的员工,来自于哪些部门的名字
– 先查询大于 5000 的员工所在的部门 id
select dept_id from emp where salary > 5000;
– 再查询在这些部门 id 中部门的名字 Subquery returns more than 1 row
select name from dept where id = (select dept_id from emp where salary > 5000);会报错
select name from dept where id in (select dept_id from emp where salary > 5000);
查询开发部与财务部所有的员工信息
– 先查询开发部与财务部的 id
select id from dept where name in(‘开发部’,‘财务部’);
– 再查询在这些部门 id 中有哪些员工
select * from emp where dept_id in (select id from dept where name in(‘开发部’,‘财务部’));
3.子查询的结果是多行多列
子查询结果只要是多列,肯定在 FROM 后面作为表
SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;
子查询作为表需要取别名,否则这张表没有名称则无法访问表中的字段
案例:查询出 2011 年以后入职的员工信息,包括部门名称
– 查询出 2011 年以后入职的员工信息,包括部门名称
– 在员工表中查询 2011-1-1 以后入职的员工
select * from emp where join_date >=‘2011-1-1’;
– 查询所有的部门信息,与上面的虚拟表中的信息组合,找出所有部门 id 等于的 dept_id
select * from dept d, (select * from emp where join_date >=‘2011-1-1’) e where d.id
= e.dept_id ;
– 也可以使用表连接
select * from emp inner join dept on emp.dept_id
= dept.id
where join_date >=‘2011-1-1’;
select * from emp inner join dept on emp.dept_id
= dept.id
and join_date >=‘2011-1-1’;
子查询小结
子查询结果只要是单列,则在 WHERE 后面作为条件
子查询结果只要是多列,则在 FROM 后面作为表进行二次查询
3.数据库事务(重点掌握) 以及数据库事务的隔离级别
3.1什么是事务
事务由单独单元的一个或者多个sql语句组成,在这个单元中,每个mysql语句是相互依赖的。
而整个单独单元作为一个不可分割的整体,如果单元中某条sql语句一旦执行失败或者产生错误,整个单元将会回滚,
也就是所有受到影响的数据将会返回到事务开始以前的状态;如果单元中的所有sql语句均执行成功,则事务被顺利执行应用场景:
在某些业务中,同时操作(update,inseret into,delete)多张表的时候(同时执行多个sql),就需要开启事务,否则在执行多个sql中如果出现异常,一部分成功,一部分失败,就会导致数据紊乱! 举例:
提交订单----->生成订单—给order以及order_item都需要插入数据
订单表 order
订单项表 order_item
商品表 product
3.2事务的特点
事务的特点:ACID
原子性:针对数据的操作要么同时成功,要么同时失败
一致性:数据的操作前后数据总量不变的
隔离性:事务就是管理业务操作,业务和业务独立,那么事务和事务是互相不影响的,是分离!
持久性:针对数据的操作,如果提交事务了,即使关机,数据永久保存!
3.3数据库事务的隔离级别
级别 | 名字 | 隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|---|
1 | 读未提交 | read uncommitted | 是 | 是 | 是 |
2 | 读已提交 | read committed | 否 | 是 | 是 |
3 | 可重复读 | repeatable read | 否 | 否 | 是 |
4 | 串行化 | serializable | 否 | 否 | 否 |
3.4数据库事务的使用方法
开启事务
start transaction;
回滚事务
rollback;
提交事务
commit;
3.5数据库隔离级别查询及更改:
查询隔离级别
mysql5.1以上至5.7查询事务的隔离级别:SELECT @@tx_isolation;
mysql8查询事务的隔离级别:SELECT @@transaction_isolation;
设置隔离级别
set global transaction isolation level 级别字符
4.引入jdbc
4.1jdbc是什么?
Java数据库连接,java可以操作各种关系型数据库
4.2jdbc的本质是什么?
本质就是一个普通的java类,数据库厂商提供的驱动jar包,来实现sun公司提供一套"应用程序接口规范"
java.sql.Drvier 驱动接口
java.sql.DriverManager:驱动管理类(管理jdbc的驱动服务)
java.sql.Connection:与特定数据库的一种会话连接
java.sql.Statement:执行静态sql语句 (执行对象,操作数据库)
5.如何操作DDL语句以及DML语句
5.1步骤:(需要背会)
- 第一步: 注册驱动(作用: 告诉Java程序,即将要连接的是哪个品牌的数据库)
- 第二步: 获取链接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完成后一定要关闭资源)
- 第三步:编写sql语句
- 第四步: 获取数据库操作对象(专门执行sql语句的对象)
- 第五步: 执行SQL语句(DQL,DML…)
- 第六步: 处理查询结果集(只有当第四步是select语句的时候,才有这第五步处理查询结果集)
- 第七步: 释放资源(使用完资源之后一定要关闭资源,Java和数据库属于进程间的通讯,开启之后一定要关闭.
5.2代码:
public class JdbcDemo {
public static void main(String[] args) throws Exception {
// 1)导包并且注册驱动
Class.forName("com.mysql.jdbc.Driver"); //mysql5.1以上5.7以下 的jar包"com.mysql.jdbc.Driver"
// mysql8.0的jar包 "com.mysql.cj.jdbc.Driver"
// 2)获取数据库的连接对象
// java.sql.DriverManager:里面有静态方法获取数据库连接对象
// public static Connection getConnection(String url, //统一资源定位符
// String user, // 当前mysql的用户名 root 用户
// String password)throws SQLException //当前mysql的登录密码
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/day11", //库名
// 使用的mysql驱动包5.7以上包括5.7以及8.0的包
// "jdbc:mysql://localhost:3306/myee_2203_02?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"
"root",
"123456"
);
// 3)准备好的sql语句
String sql = "insert into account(name,balance) values('高圆圆',1000)";
// 4)获取数据库的执行对象---执行sql语句
// 通过连接对象获取 Connection--- Statement createStatement():创建执行对象,准备将sql发送数据库
Statement stmt = conn.createStatement();
// 5)数据库的执行对象 去操作数据库
//Statement--->int executeUpdate(String sql)
int count = stmt.executeUpdate(sql);
// 6)返回结果
System.out.println("影响了" + count + "行");
// 7)释放资源
stmt.close();
conn.close();
}
}