Oracle总结
对前两天的内容的一些补充
--删除
--delete from 表名 where 行过滤条件; 删除表中满足条件的数据
select * from t_user where id in (7499,7654);
delete from t_user where id in (7499,7654);
--delete from 表名; 删除表中所有的数据
delete from t_user;
--主外键关系下两张表中数据的删除:
--删除从表中的数据,可以直接删除
delete from emp where empno = 7369;
--删除主表中的数据,不允许直接删除,前提是被从表中数据引用
delete from dept where deptno = 40;
select * from dept
select * from emp;
--如果要删除被从表引用了的主表数据:
--1)默认-->先删除从表中引用的那些数据,再删除主表数据
--2)删除主表数据的同时删除那些引用了当前主表数据的从表数据 --> on delete cascade
--3)删除主表数据,从表中那些引用了当前主表数据的外键字段设置为null --> on delete set null
-- 班级表 -->主表
--学生表--> 从表(有外键存在的表为从表) 关联了班级表的主键字段
create table yjx_class(
cid number(5) primary key,
cname varchar2(15)
)
create table yjx_student(
sid number(5) primary key,
sname varchar2(15),
--学生所在班级编号
cid number(5) references yjx_class(cid) on delete set null
)
insert into yjx_class values(202,'java49期');
insert into yjx_class values(204,'java48期');
insert into yjx_student values(1001,'zhangsan',202);
insert into yjx_student values(1002,'lisi',202);
select * from yjx_class;
select * from yjx_student;
delete from yjx_class where cid = 202;
delete from yjx_student where cid = 202;
drop table yjx_student;
--truncate 数据截断 与 delete之间的区别
--1)可以实现截断(删除)表中所有的数据 ,delete 可以删除所有|指定的数据
--2)不会开启事务,delete会默认开启事务
--3)truncate截断表中数据时候,如果表只主表,从表结构检查上不允许 delete删除主表中数据的时候三种方案-->三种
truncate table yjx_class;
select * from t_user;
create table haha(
id number(5)
)
总结
--数据库 : database 数据仓库
--oracle mysql sqlserver
--Oracle 大型 付费的数据库
--SQL 语言
设计表
前提: 设计表首先应该按需遵循三范式
1. 确定表名
2. 确定字段名 类型 +约束(主键 外键 非空 默 检查认 唯一)
主键: 唯一标识一条记录(唯一并且非空)
唯一: 唯一
非空:不能为空
默认: 当没给值时使用给定一个默认值
外键:参考其他表(自己)的某个(某些)字段
检查:自定义的规则
--DDL : 数据定义语言 表创建create 表删除drop 表修改alter
表创建create
表名必须唯一,如果存在 ,必须删除
create table 表名(
字段名 类型(长度) 约束,
...其他字段....
..约束........
)
表删除drop
drop table 表名 (cascade constraints)
--删除表
drop table emp_his;
--主从表关系下删除表
--先删除从表 再删除主表 ;同时删除约束
drop table tb_txt cascade constraints;
drop table tb_user cascade constraints;
--删除主表的同时级联删除约束
drop table emp_his cascade constraints
表修改alter
1. 修改表名 :rename to
2. 修改列名: alter table 表名 rename column to
3. 修改类型: alter table 表名 modify(字段 类型)
4. 修改约束: 先删除 后添加
5. 添加列: alter table 表名 add 字段 类型
6. 删除列:alter table 表名 drop column 字段
--DML : 数据管理语言 插入insert 删除delete 修改update
插入insert
INSERT INTO 表名称 VALUES (值1, 值2,....)
INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)
删除delete
DELETE FROM 表名称 WHERE 列名称 = 值
DELETE * FROM table_name(删除所有行)
修改update
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
UPDATE Person SET 列名称= 某值, 列名称 = 某值 ,列名称 = 某值
--DQL : 查询select
--select 数据 from 数据源,数据源.. where 行过滤条件|表连接条件 group by 分组 having 组过滤信息 order by 排序;
--select 数据 from 数据源 join 数据源 on 连接条件.. where 行过滤条件 group by 分组 having 组过滤信息 order by 排序;
select distinct *|字段|表达式 as 别名 from 表 表别名
SELECT * FROM 表名; ->查询某个表中所有的记录的所有字段信息
SELECT 列名 FROM 表名; ->查询某个表中所有的记录的指定字段信息
SELECT 列名1,列名2 FROM 表名; -> 查询某个表中所有的记录的字段1 字段2
SELECT distinct 列名 FROM 表名; ->去除重复记录
SELECT 表达式 FROM 表名; ->查询表达式
SELECT xxx as 别名 FROM 表名 表别名 ->使用别名
--索引 提高效率
前提 : 设计表首先应该按需遵循三范式
1. 确定表名
2. 确定字段名 类型 +约束(主键 外键 非空 默 检查认 唯一)
主键: 唯一标识一条记录(唯一并且非空)
唯一: 唯一
非空:不能为空
默认: 当没给值时使用给定一个默认值
外键:参考其他表(自己)的某个(某些)字段
检查:自定义的规则
索引: 提高查询速度的一种手段 -->目录
1、唯一性较好字段适合建立索引
2、大数据量才有效果
3、主键|唯一: 唯一索引
create index 索引名 on表名 (字段列表...)
drop index 索引名
create index idx_emp on emp(sal,ename);
drop index idx_emp;
select * from emp order by sal,ename
--视图
视图:建立在表|结果集|视图上的虚拟表,有以下作用
1. 简化:select 查询语句
2. 重用:封装select语句 命名
3. 隐藏:内部细节
4. 区分:相同数据不同查询
不是所有的用户都有创建视图的权限
1. 前提: create view -->组 connect resource dba
2. 授权: -->sqlplus /nolog
a)、sys登录 conn sys/123456@orcl as sysdba
b)、授权: grant dba to scott;
回收: revoke dba from scott;
c)、重新登录
--rowid 行记录地址
ROWID 是 ORACLE 中的一个重要的概念。用于定位数据库中一条记录的一个相对唯一地址值。通常情况下,该值在该行数据插入到数据库表时即被确定且唯一。ROWID 它是一个伪列,它并不实际存在于表
中。它是ORACLE 在读取表中数据行时,根据每一行数据的物理地址信息编码而成的一个伪列。所以根
据一行数据的ROWID 能找到一行数据的物理地址信息。从而快速地定位到数据行。数据库的大多数操作
都是通过ROWID 来完成的,而且使用ROWID 来进行单记录定位速度是最快的。我们可以将其用于删除
重复数据。
--rownum 结果集序号 :1、必须排序 2、不能直接取大于 1 的数
ROWNUM 是一种伪列,它会根据返回记录生成一个序列化的数字。排序后的结果集的顺序号,每一个
结果集 都有自己顺序号 ,不能直接查询大于 1 的数。利用ROWNUM,我们可以生产一些原先难以实现
的结果输出。 例如实现分页操作。
--事务 : 为了保证数据的安全有效
--控制一个事务单位中的多个操作都成功或者都失败
--ACID 特点
1. 原子性(Atomic):事务中所有数据的修改,要么全部执行,要么全部不执行。
2. 一致性(Consistence):事务完成时,要使所有所有的数据都保持一致的状态,换言之:通过事务进行的所有数据修改,必须在所有相关的表中得到反映。
3. 隔离性(Isolation):事务应该在另一个事务对数据的修改前或者修改后进行访问。
4. 持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障,也不应该丢
失。
--隔离级别-->了解
Oracle 默认的隔离级别是 read committed。
Oracle 支持上述四种隔离级别中的两种:read committed 和 serializable。除此之外, Oralce 中还定义
Read only 和 Read write 隔离级别。
Read only:事务中不能有任何修改数据库中数据的操作语句,是 Serializable 的一个子集。
Read write:它是默认设置,该选项表示在事务中可以有访问语句、修改语句,但不经常使用。
--脏读,幻读,不可重复
脏读:事务 T1 更新了一行数据,还没有提交所做的修改,T2 读取更新后的数据,T1回滚,T2 读取的数据无效,这种数据称为脏读数据。
不可重复读:事务 T1 读取一行数据,T2 修改了 T1 刚刚读取的记录,T1 再次查询,发现与第一次读取的记录不相同,称为不可重复读。
幻读:事务 T1 读取一条带 WHERE 条件的语句,返回结果集,T2 插入一条新纪录,恰好也是 T1 的WHERE 条件,T1 再次查询,结果集中又看到 T2 的记录,新纪录就叫做幻读
--结束: 提交 回滚
1. 成功
正常执行完成的 DDL 语句:create、alter、drop
正常执行完 DCL 语句 GRANT、REVOKE
正常退出的 SQLPlus 或者 SQL Developer 等客户端
如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)
手动提交 :使用 commit
2. 失败
rollback ,手动回滚
非法退出 意外的断电
JDBC
基本流程
首先得把jar包放到项目下并且加入到lib
1.加载驱动 (选择数据库)
2.建立连接 Connection (与数据库之间建立连接)
3.准备sql
4.封装处理块,发送sql(推荐使用预处理快)
5.得到结果集
6.处理结果
7.关闭资源
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动 (选择数据库)
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.建立连接 Connection (与数据库之间建立连接)
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:XE",
"SCOTT",
"TIGER"
);
//3.准备sql
String sql = "select * from dept";
//4.封装处理块
Statement state = conn.createStatement();
//5.发送sql,得到结果集
ResultSet reault = state.executeQuery(sql);
//6.处理结果
while(reault.next()){
//字段序号从1开始,每次+1
int deptno = reault.getInt(1);
String dname = reault.getString(2);
String loc = reault.getString(3);
System.out.println(deptno+"--->"+dname+"--->"+loc);
}
//7.关闭资源
reault.close();
state.close();
conn.close();
}
代码优化
ublic static void main(String[] args){
//构建 properties对象
Properties pro = new Properties();
try {
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
} catch (IOException e) {
e.printStackTrace();
}
//1.加载驱动 (选择数据库)
try {
Class.forName(pro.getProperty("driver"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2.建立连接 Connection (与数据库之间建立连接)
Connection conn = null;
Statement state = null;
ResultSet result = null;
try {
conn = DriverManager.getConnection(
pro.getProperty("url"),
pro.getProperty("username"),
pro.getProperty("password")
);
//3.准备sql
String sql = "select * from dept";
//4.封装处理块
state = conn.createStatement();
//5.发送sql,得到结果集
result = state.executeQuery(sql);
//6.处理结果
while(result.next()){
//字段序号从1开始,每次+1
int deptno = result.getInt(1);
String dname = result.getString(2);
String loc = result.getString(3);
System.out.println(deptno+"--->"+dname+"--->"+loc);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
//7.关闭资源
if(result!= null){
try {
result.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(state!=null){
try {
state.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
代码的在优化
使用代码实现以下效果
1.注册用户
2.登录用户
3.修改用户信息
4.注销用户
public static void main(String[] args){
System.out.println(update("zhangsan","321321"));;
}
//修改根据用户名修改用户密码
public static boolean update(String username,String password){
//1.获取连接
Connection conn = null;;
PreparedStatement ps = null;
boolean flag = false;
try {
conn = DBUtils.getConnection();
//设置手动提交
conn.setAutoCommit(false);
//2.构建预处理块
ps = conn.prepareStatement("update t_user set password=? where username=?");
//3.为?赋值
ps.setObject(1,password);
ps.setObject(2,username);
//4.执行,得到影响行数
int rows = ps.executeUpdate();
//5.判断
if(rows>0){
flag = true;
conn.commit(); //提交
}else{
conn.rollback(); //回滚
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DBUtils.close(ps,conn);
}
return flag;
}
//登录 : 1)根据用户名与密码一起到数据库中查询,查询到了数据登录成功,否则登录失败 2)根据用于名去查询,得到结果的密码值与用户输入的密码比较,相等登录,不等登录失败
public static boolean login(String username,String password){
//1.获取连接
Connection conn = null;
PreparedStatement state = null;
ResultSet result = null;
try {
conn = DBUtils.getConnection();
//2.准备sql
String sql = "select * from t_user where username=? and password=?";
//3.构建预处理快
state = conn.prepareStatement(sql);
//4.需要为sql中的?占位符传递参数
state.setObject(1,username);
state.setObject(2,password);
//5.执行sql,得到结果集
result = state.executeQuery(); //预处理块新增的方法 executeQuery() executeUpdate()
//5.处理结果
if(result.next()){
return true;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DBUtils.close(result,state,conn);
}
return false;
}
//修改
//注销
//注册用户
public static boolean reg(String username,String password){
//1.获取连接
Connection conn = null;
Statement state = null;
try {
conn = DBUtils.getConnection();
//2.准备sql
String sql = "insert into t_user values('"+username+"',"+password+")";
//3.构建处理快
state = conn.createStatement();
//4.执行sql,得到结果
int rows = state.executeUpdate(sql);
if(rows<=0){
return false;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DBUtils.close(state,conn);
}
return true;
}
使用到的数据库连接的封装
private static Properties pro = new Properties();
static{
//1.加载驱动
//构建 properties对象
try {
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
} catch (IOException e) {
e.printStackTrace();
}
//加载驱动 (选择数据库)
try {
Class.forName(pro.getProperty("driver"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//2.获取连接
public static Connection getConnection() throws SQLException {
Connection conn = null;
conn = DriverManager.getConnection(
pro.getProperty("url"),
pro.getProperty("username"),
pro.getProperty("password")
);
return conn;
}
//3.关闭资源
public static void close(ResultSet result, Statement state,Connection conn){
if(result!= null){
try {
result.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(state!=null){
try {
state.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(Statement state,Connection conn){
close(null,state,conn);
}
注意
预处理块的优点 :
1.防止sql注入
2.预先编译,可以提高效率
推荐使用预处理块代替静态处理快
在java中操作数据库中修改数据的时候,会自动提交事务
JDBC的扩展
public static void main(String[] args) {
BaseDao base = new BaseDao();
//System.out.println(base.update("insert into t_user values(?,?)",new Object[]{"wangwu",123})?"更新成功":"更新失败");;
System.out.println(base.update("delete from t_user where username=?",new Object[]{"wangwu"})?"更新成功":"更新失败");;
}
public static void main(String[] args) {
BaseDao<Dept> base = new BaseDao<>();
List<Dept> list = base.testQuery("select deptno \"deptno\",dname \"dname\",loc \"loc\" from dept",Dept.class);
System.out.println(list);
}
数据库通用访问对象封装 BaseDao
增删改
查询可变参数:
...表示可变参数
对应类型的形参个数有0~n个
方法的形参列表的最后存在
方法内部通过使用数组的方式使用可变参数接收的数据
注意:
在oracle中的number类型在java中默认转为java.math.BigDecimal
public List<T> testQuery(String sql,Class<T> cls,Object ...args){
//1.获取连接
Connection conn = null;
PreparedStatement ps = null;
ResultSet result= null;
ResultSetMetaData data = null;
List<T> list = new ArrayList<>(); //存储查询到的对象信息
try {
conn = DBUtils.getConnection();
//2.构建预处理块
ps = conn.prepareStatement(sql);
//3.为?赋值
if(args!=null && args.length!=0){
for(int i=0;i<=args.length-1;i++){
ps.setObject(i+1,args[i]);
}
}
//4.执行sql,得到相应行数
result = ps.executeQuery();
//结果集原信息对象
data = result.getMetaData();
//从结果集原信息对象上获取当前结果集中每条数据的字段个数
int columnCount = data.getColumnCount();
//5.处理数据
//循环遍历结果集
while(result.next()){
//查询出一条数据,对应创建java中的一个对象
T obj = cls.newInstance();
//循环获取每一个列的值,获取每一个属性,为对象属性赋值
for(int i=1;i<=columnCount;i++){
//获取每一条数据的每一个字段的值
Object value = result.getObject(i);
//判断value是否指向一个java.math.BigDecimal类型的对象,转为对应的int
if(value instanceof BigDecimal){
BigDecimal b = (BigDecimal)value;
value = b.intValue();
}
//获取字段的名字
String columnName = data.getColumnLabel(i);
//获取与字段所对应的属性
Field field = cls.getDeclaredField(columnName);
//为当前创建的对象的这个属性赋值
//忽略权限
field.setAccessible(true);
field.set(obj,value);
}
//把对象放入集合
list.add(obj);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} finally {
DBUtils.close(ps,conn);
}
return list;
}
/**
* 增删改
* @param sql 要执行的sql语句
* @param args 为?赋值的实参
* @return 成功与否
*/
public boolean update(String sql,Object[] args){
//1.获取连接
Connection conn = null;
PreparedStatement ps = null;
boolean flag = false;
try {
conn = DBUtils.getConnection();
//2.构建预处理块
ps = conn.prepareStatement(sql);
//3.为?赋值
if(args!=null && args.length!=0){
for(int i=0;i<=args.length-1;i++){
ps.setObject(i+1,args[i]);
}
}
//4.执行sql,得到相应行数
int rows = ps.executeUpdate();
//5.对相应行数判断结果
if(rows>0){
flag = true;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DBUtils.close(ps,conn);
}
return flag;
}
MyBatis
使用mybatis框架的步骤:
1.下载jar包
2.jar包资源拿到项目中,add as lib...
mybatis核心jar包
mybatis依赖jar包
数据库的驱动jar
3.定义mybatis核心配置文件--> 参考文档+官网
4.定义sql映射文件
定义要执行的sql语句
5.jar类中进行测试
加载核心配置文件
构建工厂
获取回话
执行sql
处理结果
关闭回话
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根元素: 核心配置-->
<configuration>
<!--
环境配置
default : 要使用的环境的id值
-->
<environments default="ev">
<!--environment : 一个环境的配置 id: 当前环境的唯一标识 -->
<environment id="ev">
<!--transactionManager 事务管理器 type="JDBC" :选择与jdbc相同的事务管理机制 -->
<transactionManager type="JDBC"/>
<!--数据源配置 type="POOLED" : 通过数据库连接池管理连接-->
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="username" value="SCOTT"/>
<property name="password" value="TIGER"/>
</dataSource>
</environment>
</environments>
<!--sql映射配置加载 : 定义sql语句的配置文件-->
<mappers>
<mapper resource="com/yjxxt/mappers/DeptMapper.xml"/>
</mappers>
</configuration>
javabean类
用来接受来自sql查询的数据
import java.util.Objects;
public class Dept {
private int deptno;
private String dname;
private String loc;
public Dept() {
}
public Dept(int deptno, String dname, String loc) {
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dept dept = (Dept) o;
return deptno == dept.deptno &&
Objects.equals(dname, dept.dname) &&
Objects.equals(loc, dept.loc);
}
@Override
public int hashCode() {
return Objects.hash(deptno, dname, loc);
}
@Override
public String toString() {
return "Dept{" +
"deptno=" + deptno +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
}
保存sql语句的映射xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
映射配置:
namespace 命名空间 -> 是sql映射文件的唯一标识
1) 不能重复,随便写->不推荐
2) 建议设置为当前的表名.文件名(不加后缀)
-->
<mapper namespace="com.yjxxt.mappers.DeptMapper">
<!--
select 定义查询语句
标签对中定义查询语句
id : sql语句的唯一标识
resultType : 结果类型
parameterType : 入参类型
-->
<select id="queryAll" resultType="com.yjxxt.entity.Dept" >
select * from dept
</select>
</mapper>
测试类
public static void main(String[] args) throws IOException {
//1.加载mybatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2.构建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//3.根据工厂构建回话
SqlSession session = factory.openSession();
//4.执行sql,得到结果
//selectList("命名空间.id")
List<Dept> list = session.selectList("com.yjxxt.mappers.DeptMapper.queryAll");
//5.处理结果
list.forEach(System.out::println);
//5.关闭回话
session.close();
}