Oracle:数据操作语句(DML-insertinto,update,delete)部
分。。。
数据控制语句 (DML) 部分
(1) INSERT 往数据表⾥插⼊记录的语句
INSERT INTO 表名 VALUES(所有字段都必须有值);
INSERT INTO 表名(字段名1, 字段名2, ……) VALUES ( 值1, 值2, ……);
INSERT INTO 表名(字段名1, 字段名2, ……) SELECT (字段名1, 字段名2, ……) FROM 另外的表名;
字符串类型的字段值必须⽤单引号括起来, 例如: 'GOOD DAY'。
如果字段值⾥包含单引号需要进⾏字符串转换, 我们把它替换成两个单引号。
例如:INSERT INTO TEST(ID, NAME) VALUES(10001, 'ABC''');
字符串类型的字段值超过定义的长度会出错, 最好在插⼊前进⾏长度校验。
⽇期字段的字段值可以⽤当前数据库的系统时间SYSDATE, 精确到秒;或者⽤字符串转换成⽇期型函数TO_DATE('2001-08-01','YYYY-MM-DD')。
INSERT时最⼤可操作的字符串长度⼩于等于4000个单字节, 如果要插⼊更长的字符串, 请考虑字段⽤CLOB类型, ⽅法借⽤ORACLE⾥⾃带的DBMS_LOB程序包。
INSERT时如果要⽤到从1开始⾃动增长的序列号, 应该先建⽴⼀个序列号:
CREATE SEQUENCE 序列号的名称(最好是表名+序列号标记) INCREMENT BY 1 START WITH 1 MAXVALUE 99999 CYCLE NOCACHE;
其中最⼤的值按字段的长度来定, 如果定义的⾃动增长的序列号 NUMBER(6) , 最⼤值为999999
INSERT 语句插⼊这个字段值为: 序列号的名称.NEXTVAL
(2) DELETE 删除数据表⾥记录的语句
DELETE FROM 表名 WHERE 条件;
删除记录并不能释放ORACLE⾥被占⽤的数据块表空间. 它只把那些被删除的数据块标成UNUSED, 如果确实要删除⼀个⼤表⾥的全部记录, 可以⽤ TRUNCATE 命令, 它可以释放占⽤的数据块表空间。
TRUNCATE TABLE 表名; --清除表⾥的所有记录,释放表空间,保留表结构。
(3) UPDATE 修改数据表⾥记录的语句
UPDATE 表名 SET 字段名1 = 值1, 字段名2 = 值2, …… WHERE 条件;
如果修改的值N没有赋值或定义时, 将把原来的记录内容清为NULL, 最好在修改前进⾏⾮空校验。
值N超过定义的长度会出错, 最好在插⼊前进⾏长度校验。
根据记录本⾝的某个字段值,来更新表中符合条件的所有记录。例如有个⽤户表,原来有⼀个字段2YEARS,⽤"YES"/"NO"表⽰⽤户注册是否满两年,现在需要⽤另外⼀个字段XYEARS来表⽰⽤户注册满了X年:
UPDATE USERS SET XYEARS = DECODE(2YEARS, 'YES', 2, 0);
事务控制 (TCL) 语句
COMMIT;--提交
ROLLBACK;--回滚
DML语句对表都加上了⾏级锁,确认完成后,必须加上事物处理结束的命令COMMIT才能正式⽣效,否则改变不⼀定写⼊数据库⾥。如果想撤回这些操作, 可以⽤命令 ROLLBACK 复原。
session如何设置和读取在运⾏INSERT,DELETE和UPDATE语句前最好估算⼀下可能操作的记录范围,应该把它限定在较⼩范围内,例如⼀万条记录,否则ORACLE处理这个事物⽤到很⼤的回退段。程序响应慢甚⾄失去响应。如果记录数上⼗万以上这些操作。可以把这些SQL语句分段分次完成。其间加上COMMIT确认事物处理。
事务的4个基本特征
1、原⼦性 (Atomicity )
原⼦性属性⽤于标识事务是否完全地完成,⼀个事务的任何更新要在系统上完全完成,如果由于某种原因出错,事务不能完成它的全部任务,系统将返回到事务开始前的状态。(要么全部执⾏,要么全部不执⾏)
让我们再看⼀下银⾏转帐的例⼦。如果在转帐的过程中出现错误,整个事务将会回滚。只有当事务中的所有部分都成功执⾏了,才将事务写⼊磁盘并使变化永久化。
2、⼀致性(Consistency )
事务在系统完整性中实施⼀致性,这通过保证系统的任何事务最后都处于有效状态来实现。如果事务成功地完成,那么系统中所有变化将正确地应⽤,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将⾃动地回滚,系统返回到原始状态。因为事务开始时系统处于⼀致状态,所以现在系统仍然处于⼀致状态。再让我们回头看⼀下银⾏转帐的例⼦,在帐户转换和资⾦转移前,帐户处于有效状态。如果事务成功地完成,并且提交事务,则帐户处于新的有效的状态。如果事务出错,终⽌后,帐户返回到原先的有效状态。
记住,事务不负责实施数据完整性,⽽仅仅负责在事务提交或终⽌以后确保数据返回到⼀致状态。理解数据完整性规则并写代码实现完整性的重任通常落在开发者肩上,他们根据业务要求进⾏设计。当许多⽤户同时使⽤和修改同样的数据时,事务必须保持其数据的完整性和⼀致性。
数据⼀致性指系统中每个⽤户都能够取得具备⼀致性的数据,同时还能够看到⾃⼰或其他⽤户所提交的事务对数据的修改。
3、隔离性 (Isolation)
在隔离状态执⾏事务,使它们好像是系统在给定时间内执⾏的唯⼀操作。如果有两个事务,运⾏在相同的时间内,执⾏相同的功能,事务的隔离性将确保每⼀事务在系统中认为只有该事务在使⽤系统。这种属性有时称为串⾏化,为了防⽌事务操作间的混淆,必须串⾏化或序列化请求,使得在同⼀时间
仅有⼀个请求⽤于同⼀数据。重要的是,在隔离状态执⾏事务,系统的状态有可能是不⼀致的,在结束事务前,应确保系统处于⼀致状态。但是在每个单独的事务中,系统的状态可能会发⽣变化。如果事务不是在隔离状态运⾏,它就可能从系统中访问数据,⽽系统可能处于不⼀致状态。通过提供事务隔离,可以阻⽌这类事件的发⽣。在银⾏的⽰例中,这意味着在这个系统内,其他过程和事务在我们的事务完成前看不到我们的事务引起的任何变化,这对于终⽌的情况⾮常重要。如果有另⼀个过程根据帐户余额进⾏相应处理,⽽它在我们的事务完成前就能看到它造成的变化,那么这个过程的决策可能建⽴在错误的数据之上,因为我们的事务可能终⽌。这就是说明了为什么事务产⽣的变化,直到事务完成,才对系统的其他部分可见。隔离性不仅仅保证多个事务不能同时修改相同数据,⽽且能够保证事务操作产⽣的变化直到变化被提交或终⽌时才能对另⼀个事务可见,并发的事务彼此之间毫⽆影响。这就意味着所有要求修改或读取的数据已经被锁定在事务中,直到事务完成才能释放。⼤多数数据库,通过使⽤锁定来实现隔离,事务中涉及的各个数据项或数据集使⽤锁定来防⽌并发访问。
4、持久性 (Durabilily)
持久性意味着⼀旦事务执⾏成功,在系统中产⽣的所有变化将是永久的。应该存在⼀些检查点防⽌在系统失败时丢失信息。甚⾄硬件本⾝失败,系统的状态仍能通过在⽇志中记录事务完成的任务进⾏重建。持久性的概念允许开发者认为不管系统以后发⽣了什么变化,完成的事务是系统永久的部分。在银⾏的例⼦中,资⾦的转移是永久的,⼀直保持在系统中。这听起来似乎简单,但这,依赖于将数据
写⼊磁盘,特别需要指出的是,在事务完全完成并提交后才写⼊磁盘的。所有这些事务特性,不管其内部如何关联,仅仅是保证从事务开始到事务完成,不管事务成功与否,都能正确地管理事务涉及的数据,当事务处理系统创建事务时,将确保事务有某些特性。组件的开发者们假设事务的特性应该是⼀些不需要他们亲⾃管理的特性。
为什么需要对事务并发控制
数据并发访问指多⽤户同时访问相同的数据。
如果不对事务进⾏并发控制,我们看看数据库并发操作是会有那些异常情形
1、丢失更新(Lost update)
两个事务都同时更新⼀⾏数据,但是第⼆个事务却中途失败退出,导致对数据的两个修改都失效了。
2、脏读(Dirty Reads)
⼀个事务开始读取了某⾏数据,但是另外⼀个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚。
3、⾮重复读(Non-repeatable Reads) (不可重复读)
⼀个事务对同⼀⾏数据重复读取两次,但是却得到了不同的结果。同⼀查询在同⼀事务中多次进⾏,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发⽣⾮重复读。
4、⼆类丢失更新(Second lost updates problem)
⽆法重复读取的特例。有两个并发事务同时读取同⼀⾏数据,然后其中⼀个对它进⾏修改提交,⽽另⼀个也进⾏了修改提交。这就会造成第⼀次写操作失效。
5、幻像读(Phantom Reads)
事务在操作过程中进⾏两次查询,第⼆次查询的结果包含了第⼀次查询中未出现的数据(这⾥并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外⼀个事务插⼊数据造成的。
数据库的隔离级别
为了兼顾并发效率和异常控制,在标准SQL规范中,定义了4个事务隔离级别:
1、未提交读(Read Uncommitted)
即使⼀个更新语句没有提交,但是别的事务可以读到这个改变。这是很不安全的。允许任务读取数据库中未提交的数据更改,也称为脏读。 (幻像读、⾮重复读和脏读都允许)
2、提交读(Read Committed)
可防⽌脏读,意思就是语句提交以后即执⾏了COMMIT以后别的事务就能读到这个改变。只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别。(允许幻像读、⾮重复读,不允许脏读)
3、可重复读(Repeatable Read)
在同⼀个事务⾥⾯先后执⾏同⼀个查询语句的时候,得到的结果是⼀样的。在同⼀个事务内的查询都是事务开始时刻⼀致的。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读。(允许幻想读,不允许不可重复读和脏读)
4、串⾏读(Serializable)
直译就是"序列化",意思是说这个事务执⾏的时候不允许别的事务并发执⾏。完全串⾏化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。(幻想读、不可重复读和脏读都不允许)
隔离级别对并发的控制:
丢失更新脏读⾮重复读⼆类丢失更新幻像读
未提交读Y Y Y Y Y
提交读N N Y Y Y
可重复读N N N N Y
串⾏读N N N N N
Oracle数据库⽀持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。所以Oracle不⽀持脏读。
SQL标准所定义的默认事务隔离级别是SERIALIZABLE,但是Oracle 默认使⽤的是READ COMMITTED
设置隔离级别SQL:SET TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE];
如果在每个事务开始时都使⽤ SET TRANSACTION 语句,将加重⽹络及处理器的负担。⽤户可以使⽤ ALTER SESSION 语句改变⼀个会话所有内事务的默认隔离级别:
1、ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
2、ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
(⽆法设置会话级别的只读隔离模式)
并发⼀致性问题的解决办法
1、封锁(Locking)
封锁是实现并发控制的⼀个⾮常重要的技术。所谓封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了⼀定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象。基本的封锁类型有两种:排它锁(Exclusive locks 简记为X锁)和共享锁(Share locks 简记为S锁)。
排它锁⼜称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其它事务在T释放A上的锁之前不能再读取和修改A。
共享锁⼜称为读锁。若事务T对数据对象A加上S锁,则其它事务只能再对A加S锁,⽽不能加X锁,直到T释放A上的S锁。这就保证了其它事务可以读A,但在T 释放A上的S锁之前不能对A做任何修改。
2、封锁协议
在运⽤X锁和S锁这两种基本封锁,对数据对象加锁时,还需要约定⼀些规则,例如应何时申请X锁或S锁、持锁时间、何时释放等。我们称这些规则为封锁协议(Locking Protocol)。对封锁⽅式规定不同的规则,就形成了各种不同的封锁协议。下⾯介绍三级封锁协议。三级封锁协议分别在不同程度上解决了丢失的修改、不可重复读和读"脏"数据等不⼀致性问题,为并发操作的正确调度提供⼀定的保证。
1级封锁协议是:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和⾮正常结束(ROLLBACK)。 1级封锁协议可防⽌丢失修改,并保证事务T是可恢复的。在1级封锁协议中,如果仅仅是读数据不对其进⾏修改,是不需要加锁的,所以它不能保证可重复读和不读"脏"数据。
2级封锁协议是:1级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。2级封锁协议除防⽌了丢失修改,还可进⼀步防⽌读"脏"数据。
3级封锁协议是:1级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。3级封锁协议除防⽌了丢失修改和不读'脏'数据外,还进⼀步防⽌了不可重复读。
⼀般处理并发问题时的步骤:
1、开启事务。
2、申请写权限,也就是给对象(表或记录)加锁。
3、假如失败,则结束事务,过⼀会重试。
4、假如成功,也就是给对象加锁成功,防⽌其他⽤户再⽤同样的⽅式打开。
5、进⾏编辑操作。
6、写⼊所进⾏的编辑结果。
7、假如写⼊成功,则提交事务,完成操作。
8、假如写⼊失败,则回滚事务,取消提交。
9、(7.8)两步操作已释放了锁定的对象,恢复到操作前的状态。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论