SQL Fundamentals: 数据更新及事务处理(INSERT INTO,UPDATE,DELETE,事务,锁)
SQL Fundamentals || Oracle SQL语言
在SQL语句中,数据操作语言DML由两部分组成,查询(DQL)、更新操作(增加,修改,删除).
- 增加数据(INSERT INTO)
- 数据的更新操作(UPDATE)
- 数据的删除操作(DELETE)
- 事务处理
- 锁
1.增加数据(INSERT INTO)
- 数据增加操作指的是向数据表中添加一条新的记录,而对于数据的插入通常有两种形式:
一:插入一条新的数据 |
INSERT INTO 表名称 [(列1,列2,列3,…)] VALUES (值1,值2,值3,…) ; |
二:插入子查询的返回结果 |
INSERT INTO 表名称 [(列1,列2,列3,…)] 子查询 ; |
- 所接触到的数据主要有三种(VARCHAR2、NUMBER、DATE),所以此时对于这三种数据在增加语法之中的编写要求如下:
NUMBER类型: |
直接编写,例如:123; |
VARCHAR2类型: |
使用“'”声明,例如:“'MLDN'” (CLOB类型也按照同样的方式进行); |
DATE类型: |
可以按照已有的日期格式编写字符串,例如:“'22-2月 -81'”, 或者是使用TO_DATE()函数将字符串变为DATE型数据, 而如果为当前日期时间,则直接使用SYSDATE; |
增加新数据,范例
插入一条新的数据 |
向myemp数据表之中增加一条新的数据 使用完整语法进行数据增加时需要写上要增加数据的列的名称; |
INSERT INTO myemp(empno,job,hiredate,ename,mgr,sal,comm,deptno) VALUES (8888,'CLERK',SYSDATE,'WENDY',7369,800,100,20); |
通过子查询添加数据 |
编写完整格式将所有20部门雇员的信息插入到myemp表之中: |
INSERT INTO myemp(empno,ename,job,mgr,hiredate,sal,comm,deptno) SELECT * FROM emp WHERE deptno=20 ; |
2.数据的更新操作(UPDATE)
数据库的更新操作主要是指的对数据表中的数据进行修改,与数据的增加一样,在数据修改的时候有两种形式:
一:由用户自己指定要更新数据的内容 |
UPDATE 表名称 SET 字段=值 [,字段=值,...] [WHERE 更新条件(s)] |
二:基于子查询的更新 |
UPDATE 表名称 SET (column,column,...)=(SELECT column,column,... FROM table WHERE 查询条件(s)) |
数据更新时可以直接设置更新数据也可以通过子查询取得更新数据.
3、更新数据,范例(先写条件,再写更新数据)
由用户自己指定要更新数据的内容 |
将SMITH(雇员编号为7369)的工资修改为3000元,并且每个月有500元的奖金 |
UPDATE myemp SET sal=3000,comm=500 WHERE empno=7369; |
基于子查询的更新 |
将工资低于公司平均薪金的雇员的基本工资上涨20% |
UPDATE myemp SET sal=sal*1.2 WHERE sal<( SELECT AVG(sal) FROM myemp) ; |
一次性上涨公司全部雇员的基本工资,每个雇员的基本工资上涨10% |
UPDATE myemp SET sal=sal*1.1 ; |
将雇员7369的职位、基本工资、雇佣日期更新为与7839相同的信息 |
UPDATE myemp SET (job,sal,hiredate)=(SELECT job,sal,hiredate FROM myemp WHERE empno=7389) WHERE empno=7369 ; |
4. 数据的删除操作(DELETE)
当数据表中的某些数据不再需要时,就可以通过删除语句进行删除.
删除数据时如果没有指定删除条件,那么就表示删除全部数据.
设置的删除条件可以指定具体的数据也可以设置子查询.
语法:
DELETE FROM 表名称 [WHERE 删除条件] ;
更新数据,范例(先写条件,再写更新数据)
删除具体的数据 |
删除雇员编号是7566的雇员信息 删除30部门内的所有雇员 删除雇员编号为7369、7566、7788的雇员信息 |
DELETE FROM myemp WHERE empno=7566 ; DELETE FROM myemp WHERE deptno=30 ; DELETE FROM myemp WHERE empno IN (7369,7566,7788) ; |
删除子查询的结果 |
删除公司工资最高的雇员 |
DELETE FROM myemp WHERE sal=( SELECT MAX(sal) FROM myemp) ; |
日期条件 |
DELETE FROM myemp WHERE TO_CHAR(hiredate,'yyyy')=1987; |
更新行数:
对于更新的三个操作:增加、修改、删除,每一次都一定会返回当前操作所影响到的数据行数,在java的JDBC操作中更新数据的操作statement和preparedstatement两个接口,调用的方法是executeUpdate(),返回的是一个int型数据,就是接收更新的行数.
5.事务处理
事务处理在数据库开发中有着非常重要的作用,所谓的事务核心概念就是指一个SESSION所进行的所有更新操作要么一起成功,要么一起失败,
事务本身具有:原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation)、持久性(Durabilily)四个特征,以上的四个特征,也被称为ACID特征。
Oracle中事务操作命令
命令 |
描述 |
SET AUTOCOMMIT=OFF |
取消掉自动提交处理,开启事务处理 |
SET AUTOCOMMIT=ON |
打开自动提交处理,关闭事务处理 |
COMMIT |
提交事务 |
ROLLBACK TO [回滚点] |
回滚操作 |
SAVEPOINT 事务保存点名称 |
设置事务保存点 |
关于SESSION
Oracle 连接(connection)与会话(session)
- 连接:Communication between a user process and an instance
- 会话:Specific connection of a user to an instance through a user process
在Oracle数据库之中,每一个连接到此数据库的用户都是一个“SESSION”,每一个SESSION都拥有独立的事务,都可以使事务操作命令,不同的SESSION事务是完全隔离的。
服务器依靠SESSION来区分不同的用户,所以每个会话表示每个用户。
更新缓冲
对于每一个SESSION而言,每一个数据库的更新操作在事务没有被提交之前都只是暂时保存在了一段缓冲区之中,并不会真正的向数据库中发出命令,如果现在用户发现操作有问题了,则可以进行事务的回滚。
回滚存储点
在默认情况下,执行ROLLBACK命令意味着全部的操作都要回滚,如果现在希望可以回滚到指定操作的话,则可以采用SAVEPOINT设置一些保存点,这样在回滚的时候,就可以通过ROLLBACK返回指定的保存点上。
事务自动提交
设置事务是否自动提交 |
SET AUTOCOMMIT [ON|OFF] |
掌握事务的处理命令 |
COMMIT、ROLLBACK。 |
范例
打开第一个session |
删除超过32年雇佣的雇员; 原本有14条数据,删除了11条,还有3条数据 |
DELETE FROM myemp WHERE MONTHS_BETWEEN(SYSDATE,hiredate)/12>32; |
打开第二个session |
执行查询操作,发现在session2中数据仍然有14条数据, 因为更新缓冲,对于每一个SESSION而言,每一个数据库的更新操作在事务没有被提交之前都只是暂时保存在了一段缓冲区之中,并不会真正的向数据库中发出命令,如果现在用户发现操作有问题了,则可以进行事务的回滚rollback。 |
回到第一个session |
进行事务回滚ROLLBACK;执行完后再查看数据,14条数据又回来了。 如果执行完删除操作后,现在执行了COMMIT;那么表示正在的发出了更新指令。 |
回到第二个session |
此时session中查询数据时发现数据已经被更新了。 |
设置存储点 |
INSERT INTO myemp(empno,ename) VALUES(2222,'gaga'); UPDATE myemp SET sal=7000 WHERE empno=2222; SAVEPOINT sp_a; INSERT INTO myemp(empno,ename) VALUES(3333,'nacy'); UPDATE myemp SET sal=4000 WHERE empno=3333; SAVEPOINT sp_b;
DELETE FROM myemp WHERE empno in(2222,3333);---------删除雇员数据 SELECT * FROM myemp;
ROLLBACK TO sp_b; ROLLBACK TO sp_a; |
6.锁
不同的session同时操作同一资源所发生的问题。
数据只能被一个session操作。
锁表 for update
select for update 是为了在查询时,避免其他用户以该表进行插入,修改或删除等操作,造成表的不一致性.
出现锁的情况
第一个SESSION(scott/tiger连接)执行以下操作
SELECT * FROM myemp WHERE deptno=10 FOR UPDATE ;
第二个SESSION(scott/tiger连接)执行同样的操作(这个时候就产生了锁,只能等待)
SELECT * FROM myemp WHERE deptno=10 FOR UPDATE ;
锁的产生
锁是在多个SESSION访问同一资源时出现的状态;
锁的分类
在Oracle中的锁有以下两种基本类型:
行级锁定 记录锁定 |
对当前事务中的一行数据以独占的方式进行锁定,在此事务结束之前,其他事务要一直等待该事务完结,例如:之前的范例演示的就是行级锁定; |
表级锁定 |
对整张数据表进行数据锁定,只允许当前事务访问数据表,其他事务无法访问。 |
行级锁定
- 用户执行了INSERT、UPDATE、DELETE以及SELECT FOR UPDATE语句时,Oracle将隐式的实现记录的锁定,这种锁定被称为排它锁。
- 这种锁的主要特点是:
当一个事务执行了相应的数据操作之后,如果此时事务没有提交,那么会一直以独占的方式锁定这些操作的数据,其他事务一直到此事务释放锁后才可以进行操作。
表级锁定
表级锁定需要用户明确的使用“LOCK TABLE”语句手工进行锁定
LOCK TABLE 表名称 | 视图名称, 表名称 | 视图名称,… IN 锁定模式 MODE [NOWAIT];
NOWAIT:这是一个可选项,当视图锁定一张数据表时,如果发现已经被其他事务锁定,不会等待;
锁定模式有如下几种常见模式:
ROW SHARE |
行共享锁,在锁定期间允许其他事务并发对表进行各种操作,但不允许任何事务对同一张表进行独占操作(禁止排它锁); |
ROW EXCLUSIVE |
行排它锁,允许用户进行任何操作,与行共享锁不同的是它不能防止别的事务对同一张表进行手工锁定或独占操作; |
SHARE |
共享锁,其它事务只允许执行查询操作,不能执行修改操作; |
SHARE ROW EXCLUSIVE |
共享排它锁,允许任何用户进行查询操作,但不允许其他用户使用共享锁,之前所使用的“SELECT FOR UPDATE”就是共享排它锁的常见应用; |
EXCLUSIVE |
排它锁,事务将以独占方式锁定表,其他用户允许查询,但是不能修改,也不能设置任何的锁。 |
范例:LOCK TABLE myemp IN SHARE MODE NOWAIT ;
解除锁定
尽管用户清楚了锁产生的原因,但是在很多时候由于业务量的增加,可能并不会像本章那样为用户清楚的罗列出现锁的种种可能,所以此时就必须通过其它方式查看是否出现了锁定以及通过命令手工的解除锁定。
解除锁定语法:
ALTER SYSTEM KILL SESSION 'SID , SERIAL#'
在此格式之中发现如果要想结束一个SESSION(结束一个SESSION就表示解锁),则需要两个标记:
- SESSION ID(SID)(每一个用户的SESSION由管理员分配)
- 序列号(SERIAL#)
而这两个内容可以利用的数据字典:“v$locked_object”和“v$session”
解除锁定准备
第一个SESSION(scott/tiger连接)执行以下操作
SELECT * FROM myemp WHERE deptno=10 FOR UPDATE ;
第二个SESSION(scott/tiger连接)执行同样的操作
SELECT * FROM myemp WHERE deptno=10 FOR UPDATE ;
管理员解锁(sys/change_on_install)
- 查看数据库中的锁定情况(v$locked_object)
SELECT session_id,oracle_username,process from v$locked_object ;
- 查询v$session数据字典
SELECT sid,serial#,username,lockwait,status FROM v$session where sid IN (17,245,477) ;
- 解除死锁(注意,这里的'245,2867'分别是sid和serial#)
ALTER SYSTEM KILL SESSION '245,2867';
补充一点:查询当前session的sid的方法(v$mystat): select distinct sid from v$mystat;