Delete
delete [from] 表名 where 过滤行记录
说明:
- delete 可以删除指定部分记录,删除全部记录
- 记录上存在主外键关联时, 删除存在关联的主表的记录时,注意 参考外键约束, 约束强制不让删除
先删除从表 再删除主表
--删除全部数据
delete from tb_user where 1=1;
--删除指定数据
delete from tb_user where userid<10;
--主外键关联时,注意 参考约束, 约束强制不让删除
--默认先删除从表 再删除主表
delete from tb_txt where 1=1;
delete from tb_user where 1=1;
commit;
--删除主表数据,并设置从表数据为null
--删除主表数据,级联删除从表数据
截断数据
truncate: 截断所有的数据 ,如果截断的是主表,结构不能存在外键关联,截断数据同时从结构上检查
create table emp_his as select * from emp where 1=1;
select * from emp_his;
--截断所有的数据
truncate table emp_his;
--不能截断: truncate table dept;
截断数据与删除数据区别 truncate 与delete 区别
1、truncate -->ddl ,不涉及事务,就不能回滚
delete -->dml ,涉及事务,可以回滚
2、truncate 截断所有的数据 delete 可以删除全部 或者部分记录
3、truncate从结构上检查是否存在主外键,如果存在,不让删除
delete 从记录上检查是否存在主外键,如果存在,按参考外键约束进行删除。
事务
事务有一下四个特点:(ACID)
- 原子性(Atomic):事务中所有数据的修改,要么全部执行,要么全部不执行。
- 一致性(Consistence):事务完成时,要使所有所有的数据都保持一致的状态,换言之:通过事
务进行的所有数据修改,必须在所有相关的表中得到反映。 - 隔离性(Isolation):事务应该在另一个事务对数据的修改前或者修改后进行访问。
- 持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障,也不应该丢
失。
事务的隔离级别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CJy6rmbM-1627690913931)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627654491192.png)]
Oracle 默认的隔离级别是 read committed。
Oracle 支持上述四种隔离级别中的两种:read committed 和 serializable。除此之外, Oralce 中还定义
Read only 和 Read write 隔离级别。
Read only:事务中不能有任何修改数据库中数据的操作语句,是 Serializable 的一个子集。
Read write:它是默认设置,该选项表示在事务中可以有访问语句、修改语句,但不经常使用。
丢失更新:两个事务同时存储, 一个存储 100 , 一个存储 200,最终可能至存储了 200 或者 100,那
另一个的更新就没成功,即结果不为预想的 300
脏读:事务 T1 更新了一行数据,还没有提交所做的修改,T2 读取更新后的数据,T1回滚,T2 读取的数
据无效,这种数据称为脏读数据。
不可重复读:事务 T1 读取一行数据,T2 修改了 T1 刚刚读取的记录,T1 再次查询,发现与第一次读取
的记录不相同,称为不可重复读。
幻读:事务 T1 读取一条带 WHERE 条件的语句,返回结果集,T2 插入一条新纪录,恰好也是 T1 的
WHERE 条件,T1 再次查询,结果集中又看到 T2 的记录,新纪录就叫做幻读。
事务的开启
自动开启于 DML 之 insert delete update
事务的结束
- 成功
正常执行完成的 DDL 语句:create、alter、drop
正常执行完 DCL 语句 GRANT、REVOKE
正常退出的 SQLPlus 或者 SQL Developer 等客户端
如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)
手动提交 :使用 commit - 失败
rollback ,手动回滚
非法退出 意外的断电
rollback 只能对未提交的数据撤销,已经 Commit 的数据是无法撤销的,因为 commit 之后已经持久化到数据库中。
JDBC
接口名称 | 作用 |
---|---|
java.sql.Connection | 连接 |
java.sql.Statement | 静态处理块 |
java.sql.PreparedStatement | 预处理块 |
java.sql.ResultSet | 结果集 |
java.sql.ResultSetMetaData | 结果集元信息 |
jdbc步骤
- 加载驱动(选择数据库)
- 建立连接
- 准备sql
- 封闭处理块,发送sql
- 得到结果集
- 处理结果
- 关闭资源
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-01JIQsM6-1627690913933)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627655046111.png)]
import java.sql.*;
public class Class001_jdbc01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//加载驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//建立连接
Connection con = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:XE",
"SCOTT",
"TIGER"
);
//准备sql
String sql="select * from dept";
//封装处理块
Statement state=con.createStatement();
//发送SQL,得到结果集
ResultSet resultSet=state.executeQuery(sql);
//处理结果集
while (resultSet.next()){
int deptno=resultSet.getInt(1);
String dname=resultSet.getString(2);
String loc=resultSet.getString(3);
System.out.println(deptno+"-->"+dname+"-->"+loc);
}
//关闭资源
resultSet.close();
state.close();
con.close();
}
}
建立连接
驱动: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@db 服务器地址:端口:实例
连接 url->jdbc:oracle:thin:@localhost:1521:XE
用户名: SCOTT
密码: TIGER
Connection con =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","SCOTT
","TIGER");
处理块
1.静态处理块Statement
Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连接的基础上,向数据库发送要执行的 SQL 语句。Statement 对象,用于执行不带参数的简单 SQL 语句。
执行静态 SQL 语句并返回它所生成结果的对象。
特点:
处理 不变的静态的 sql 语句
优点: 直接查看sql ,方便处理错误
缺点:性能不高 拼接 sql 麻烦 可能存在 sql 注入
2.预处理块 PreparedStatemen
PreparedStatement 接口继承了 Statement,并与之在两方面有所不同:有人主张,在 JDBC 应用中,如果你已经是稍有水平开发者,你就应该始终以 PreparedStatement 代替 Statement.也就是说,在任
何时候都不要使用 Statement。
由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。
特点:
处理 不变的静态的 sql 语句 |可变的 sql 语句 带 ? 的 sql
优点:性能高,方便编写sql 不存在sql注入 安全
缺点:不能直接打印sql语句 不方便处理错误
对固定代码进行封装:
/*
JDBC工具类
1.加载驱动
2.获取连接
3.关闭资源
*/
public class DBUtil {
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("server"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//2.获取连接
public static Connection getConnection() throws SQLException {
Connection con=null;
con= DriverManager.getConnection(
pro.getProperty("url"),
pro.getProperty("user"),
pro.getProperty("password")
);
return con;
}
//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);
}
}
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class BaseBao<T> {
public List<T> testQuery(String sql,Class<T> cls,Object ...args){
//1.获取连接
Connection con=null;
PreparedStatement psstate=null;
ResultSet result=null;
ResultSetMetaData data=null;
List<T> list=new ArrayList<>();//存储查询到对象信息
try {
con=DBUtil.getConnection();
//构建预处理块
psstate=con.prepareStatement(sql);
//为?赋值
if(args!=null && args.length!=0){
for(int i=0;i< args.length;i++){
psstate.setObject(i+1,args[i]);
}
}
//执行sql,得到相应行数
result=psstate.executeQuery();
//结果集源对象信息
data = result.getMetaData();
//从结果集原信息对象上获取当前结果集中每条数据的字段个数
int columnCount=data.getColumnCount();
//处理数据
//循环遍历结果集
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 big= (BigDecimal)value;
value=big.intValue();
}
//获取字段的名字
String columnName= data.getColumnName(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();
}
return list;
}
/**
* 增删改
* @param sql 要执行的sql语句
* @param args 为?赋值的实参
* @return 成功与否
*/
public boolean base(String sql,Object[] args){
Connection con=null;
PreparedStatement psstate=null;
try {
con=DBUtil.getConnection();
psstate=con.prepareStatement(sql);
if(args!=null && args.length!=0){
for (int i=0;i<args.length;i++){
psstate.setObject(i+1,args[i]);
}
}
int rows=psstate.executeUpdate();
if(rows>0){
return true;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
DBUtil.close(null,psstate,con);
}
return false;
}
}
/*
JDBC工具类
1.加载驱动
2.获取连接
3.关闭资源
*/
public class DBUtil {
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("server"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//2.获取连接
public static Connection getConnection() throws SQLException {
Connection con=null;
con= DriverManager.getConnection(
pro.getProperty("url"),
pro.getProperty("user"),
pro.getProperty("password")
);
return con;
}
//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);
}
}
对表进行操作:
import com.yjx.util.DBUtil;
import java.sql.*;
/*
对用户进行操作
1.注册用户
2.登录用户
3.修改用户信息
4.注销用户
预处理块的优点 :
1.防止sql注入
2.预先编译,可以提高效率
推荐使用预处理块代替静态处理块
注意:
在java中操作数据库中修改数据的时候,会自动提交事务
*/
public class Class003_User {
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 = DBUtil.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 {
DBUtil.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 = DBUtil.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 {
DBUtil.close(result,state,conn);
}
return false;
}
//修改
//注销
//注册用户
public static boolean reg(String username,String password){
//1.获取连接
Connection conn = null;
Statement state = null;
try {
conn = DBUtil.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 {
DBUtil.close(state,conn);
}
return true;
}
}
释放资源
释放资源的原则是 先打开的后关闭, 则我们的顺序一般为: 结果集->处理块->连接