ORACLE 操纵数据&&锁&&事务
INSERT语句语法
使用INSERT语句添加新行到表中
INSERT INTO table [(column [, column...])]
VALUES (value [, value...]);
用该语法一次只能插入一行
注:该语句用VALUES子句添加行到表中,一次仅一行。
插入新行
:插入一个包含每一个列值的新行
:值以表中列的默认顺序列表
:在INSERT子句中字段可以随意列表
INSERT INTO departments(department_id, department_name, manager_id, location_id)VALUES (70, 'Public Relations', 100, 1700);1 row created.
:字符和日期要用单引号括起来,数字值不需要。
数字值不应放在单引号中,因为对于指定为NUMBER数据类型的字段,如果使用了单引号,可能会发生数字值的隐式转换。
插入带空值的行
::隐式方法: 省略字段列表中的列
INSERT INTO departments (department_id, department_name)VALUES(30, 'Purchasing');
1 row created
::显式方法: 在VALUES子句中指定NULL关键字
INSERT INTO departments
VALUES (100, 'Finance', NULL, NULL);
1 row created.
插入空值的方法:
隐式:从字段列表中省略列。
显式:在values列表中指定NULL关键字,对于字符串和日期,在在values列表中指定空符串('')
在插入新行时,任何没有被明确列出的字段都将获得一个空值。
在用户输入时经常出现的错误:
:: 对于NOT NULL列缺少强制的值
:: 重复值违反了唯一性约束
:: 违反外键约束
:: 违反CHECK约束
:: 数据类型不匹配
:: 值的宽度超过了列的限制
在插入行到表中时,你也可以用USER函数,USER函数记录当前用户名。
也可以用SYSDATE用在VALUES列表中.
插入特殊日期值.
SQL> desc employees;
名称 是否为空? 类型
----------------------------------------- -------- --------------
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)
INSERT INTO employees
VALUES (114, 'Den', 'Raphealy', 'DRAPHEAL',
'515.127.4561',TO_DATE('FEB 3, 1999', 'MON DD, YYYY'),
'AC_ACCOUNT', 11000, NULL, 100, 30);
主要看日期格式:
SQL> select *
2 from employees
3 where employee_id=114;
EMPLOYEE_ID FIRST_NAME LAST_NAME
----------- -------------------- -------------------------
EMAIL PHONE_NUMBER HIRE_DATE JOB_ID
------------------------- -------------------- --------- ----------
COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
-------------- ---------- -------------
114 Den Raphaely
DRAPHEAL 515.127.4561 07-DEC-94 PU_MAN
100 30
如果在values中写为'03-FEB-99' 则插入的是2099年
从另一个表中复制行
:用一个子查询写insert语句
INSERT INTO sales_reps (id, name, salary, commission_pct)
SELECT employee_id, last_name, salary, commission_pct
FROM employees
WHERE job_id LIKE '%REP%';
:不用VALUES子句.
:子查询中列的数目要匹配INSERT子句中列的数目.
INSERT INTO table [ column (, column) ] subquery;
在INSERT子句的字段列表中列的数目和它们的数据类型必须与子查询中的值的数目及其数据类型相匹配。
为了创建一个表的行的拷贝,在子查询中用SELECT * 。
INSERT INTO copy_emp
SELECT *
FROM employees;
改变表中的数据.
update table
set column=value [,column=value, ...]
[where condition];
:如果需要,一次更新多行.
注:通常 ,用主键标识一个单个的行,如果用其他列,可能会出乎意料的引起另一些行被更新.例如,在employees表中用名字标识一个单个的行是危险的,因为没的雇员可能有相同的名字.
(更新行时,用主键唯一标识一个行.)
update employees
set department_id=70
where employee_id=113;
如果where子句被指定,update将修改指定的行.将雇员号113(Popp)转到部门70.
如果没有where子句,表中所有的行都会被修改.
update copy_emp
set department_id=110;
更新雇员114的工作和薪水,使其和雇员205相同
UPDATE employees
SET job_id = (SELECT job_id FROM employees WHERE employee_id = 205),
salary = (SELECT salary FROM employees WHERE employee_id = 205)
WHERE employee_id = 114;
语法
UPDATE table
SET column =
(SELECT column
FROM table
WHERE condition)
[ ,
column =
(SELECT column
FROM table
WHERE condition)]
[WHERE condition ] ;
在UPDATE语句中用子查询来更新基于另一个表中值的那些行
UPDATE copy_emp
SET department_id = (SELECT department_id FROM employees WHERE employee_id = 100)
WHERE job_id = (SELECT job_id FROM employees WHERE employee_id = 200);
用基于来自EMPLOYEES表的值更新COPY_EMP表,它用employee 100的部门号;改变所有工作岗位与employee 200的工作岗位相同的那些雇员的部门号。
注意:企图用有完整性约束依赖的值更新记录,会出现错误。
从表中删除行.
在所有的行用DELETE语句删除后,只有表的数据结构被保留,清空表的另一种更有效的方法是用TRUNCATE语句.
你可以用TRUNCATE语句快速删除表中所有的行,用TRUNCATE语句删除行比用DELETE语句更快一些,原因如下:
TRUNCATE语句是数据定义语言 (statement is a data definition language DDL) 语句,不产生回退信息,TRUNCATE语句在子查询课程中讲述。
截断表不触发表的删除触发器。
如果表是引用完整性约束的父表,你不能截断该表,在发布TRUNCATE语句之前先禁用约束。
Delete [from] table
[where condition];
DELETE语句执行前没有确认提示,但是,删除操作直到数据处理事务被提交之前不会被持久化,因此,如果你做错了,可以用ROLLBACK语句撤消删除操作。
如果指定了WHERE子句,则指定的行被删除
DELETE FROM departments
WHERE department_name = 'Finance';
1 rows deleted.
如果遗漏了WHERE子句,表中所有的行都被删除从表中删除行
DELETE FROM deaprtments
22 rows deleted.
删除基于另一个表的行
在DELETE语句中用子查询来删除表中的基于另一个表中值的行
DELETE FROM employees
WHERE department_id =(SELECT department_id
FROM departments
WHERE department_name LIKE '%Public%');
删除所有雇员,这些雇员所在的部门是部门名字中包含字符串“Public”的那些部门。
过程:
子查询查找DEPARTMENTS表以找出基于部门名中包含字符串“Public”的部门的部门号。子查询然后将部门号馈入主查询,主查询基于该部门号从EMPLOYEES删除数据行。
注意:不能删除包含主键的行,该主键被用做另一个表的外键
如果你试图删除的父记录有子记录,那么,你将收到child record found violation ORA-02292。
如果你尝试删除一条记录,该记录中的值依赖一个完整性约束,一个错误被返回。
delete from departments
where department_id=60;
ora-02292
下面的语句可以正常工作,因为在部门70中没有雇员.
delete from departments
where department_id=70;
注:如果使用了引用完整性约束,当你试图删除一行时,你可能收到一个Oracle服务器错误信息。但是,如果引用完整性约束包含了ON DELETE CASCADE选项,那么,可以删除行,并且所有相关的子表记录都被删除。
SELECT employee_id, last_name,email, hire_date, job_id, salary, department_id
FROM employees
WHERE department_id = 50
在INSERT语句中使用子查询
INSERT INTO
(SELECT employee_id, last_name,email,
hire_date, job_id, salary, department_id
FROM employees
WHERE department_id = 50)
VALUES (99999, 'Taylor', 'DTAYLOR',
TO_DATE('07-JUN-99', 'DD-MON-RR'),'ST_CLERK', 5000, 50);
1 row created.
其中
SELECT employee_id, last_name,email,
hire_date, job_id, salary, department_id
FROM employees
WHERE department_id = 50
查出45条记录.
在INSERT语句的INTO子句中用一个子查询代替表名,该子查询的选择列表必须与VALUES子句的字段列表有相同的字段数,基表的列上的所有规则必须遵循INSERT语句的顺序。
你不可能插入一个重复的employee_id,也不能遗漏强制为非空列的值。(非空列要有值)
子查询用于为INSERT语句标识所要操作的表。
在DML 语句中使用WITH CHECK OPTION关键字
::一个子查询被用于确定表和DML 语句的列
::WITH CHECK OPTION 关键字禁止改变那些不在子查询中的行
INSERT INTO (SELECT employee_id, last_name, email,
hire_date, job_id, salary
FROM employees
WHERE department_id = 50 WITH CHECK OPTION)
VALUES (99998, 'Smith', 'JSMITH',
TO_DATE('07-JUN-99', 'DD-MON-RR'), 'ST_CLERK', 5000);
INSERT INTO
*
ERROR at line 1:
ORA-01402: view WITH CHECK OPTION where-clause violation
如果子查询被用于在INSERT、UPDATE或DELETE语句中代替表,那些没有包括在子查询中提供给该表的行将不会改变。
WITH CHECK OPTION关键字
指定WITH CHECK OPTION预示,如果子查询被用于在INSERT、UPDATE或DELETE语句中代替表,那些没有包括在子查询中提供给该表的行将不会改变。(本例中department_id)
如例子中显示,使用了WITH CHECK OPTION关键字,子查询确定部门号为50的行,但部门号不在SELECT列表中,并且在VALUES列表中也没有提供相应的值。插入该行将导致一个空的部门号,该行不在子查询中
显式默认特性概览
::用显式默认特性,你能够用DEFAULT关键字作为一个列值,该列要求一个默认值
::该特性允许用户控制在什么地方和什么时候默认值应该被提供给数据
::显示默认值能够被用于INSERT和UPDATE语句
DEFAULT关键字可以被用于INSERT和UPDATE语句来确定默认的列值。如果不存在默认值,将使用空值。
使用显示默认值
在INSERT中的DEFAULT:
INSERT INTO departments(department_id, department_name, manager_id)
VALUES (300, 'Engineering', DEFAULT);
在UPDATE中的DEFAULT:
UPDATE departments SET manager_id = DEFAULT
WHERE department_id = 10;
指—EFAULT用预先指定的值作为该列的默认值。如果相应的列无指定的默认值,Oracle设置该列为空。
第一个例子显示,INSERT语句的VALUES子句给MANAGER_ID字段一个默认值,如果对该列无默认值定义,作为代替将插入一个空值。
第二个例子中,UPDATE语句的SET子句赋给部门10的MANAGER_ID列一个默认值,如果对该列无默认值定义,该值将变为空。
注:在创建表时,你可以为一个字段指定默认值。默认值将在课程 “创建和管理表” 中讨论
MERGE语句(合并行)
::提供有条件地更新和插入数据到数据库表中的能力是执行对目的表的更新操作还是执行对目的表的插入操作,取决于基于ON子句中的条件。
::如果行存在,执行UPDATE;如果是一个新行,执行INSERT:
避免分散更新
增进性能和易用性
在数据仓库应用中有用
由于MERGE命令组合了INSERT和UPDATE命令,你需要有对目的表的INSERT和UPDATE权限,以及对源表的SELECT权限。
一个可供选择近似方法是用PL/SQL循环和多重DML语句
用MERGE语句,你可以有条件地添加或修改行。
语法:
MERGE INTO table_name table_alias
USING (table|view|sub_query) alias
ON (join condition)
WHEN MATCHED THEN
UPDATE SET col1 = col_val1,
col2 = col2_val
WHEN NOT MATCHED THEN
INSERT (column_list)
VALUES (column_values);
合并行
用MERGE语句,你可以更新已经存在的行,并且有条件地插入新行。
在语法中:
INTO子句 指定你正在更新或插入的目的表
USING子句 指定数据源要被更新或插入的数据的源;可以是一个表、视图或者字查询
ON 子句 是一个条件,在此条件上MERGE操作即可以更新也可以插入
WHEN MATCHED | 通知服务器怎样响应连接条件的结果
WHEN NOT MATCHED
条件c.employee_id = e.employee_id被测试,因为COPY_EMP表为空,条件返回:没有相匹配的行,逻辑进入到WHEN NOT MATCHED子句中,并且MERGE命令插入EMPLOYEES表的行到COPY_EMP表中。
如果COPY_EMP表中存在记录,并且employee IDs在两个表中匹配 (COPY_EMP和EMPLOYEES表),COPY_EMP表中已经存在的行将被EMPLOYEES表中相匹配的行更新。
SELECT * FROM COPY_EMP;
no rows selected
>>
SELECT * FROM COPY_EMP;
20 rows selected
MERGE INTO copy_emp c
USING employees e
on (c.employee_id = e.employee_id)
WHEN MATCHED THEN
UPDATE SET
c.first_name = e.first_name,
c.last_name = e.last_name,
c.email = e.email,
c.phone_number = e.phone_number,
c.hire_date = e.hire_date,
c.job_id = e.job_id,
c.salary = e.salary,
c.commission_pct = e.commission_pct,
c.manager_id = e.manager_id,
c.department_id = e.department_id
WHEN NOT MATCHED THEN
INSERT VALUES(e.employee_id, e.first_name, e.last_name,
e.email, e.phone_number, e.hire_date, e.job_id,
e.salary, e.commission_pct, e.manager_id,
e.department_id);
.employee_id = e.employee_id)
在数据仓库环境中,你可能有一个大的事实表和一个较小维数的表,小表中的行需要有条件地插入到大的事实表中。在这种情况下,MERGE语句是有用的。
数据库事务处理
数据库事务处理由下面的语句组成:
::DML 语句,对数据进行永久的改变
::DDL 语句
::DCL 语句
事务由包装成一个整体更改数据的DML语句组成
事务类型
类型说明
数据操纵语言 (Data manipulation由许多 DML 语句组成,Oracle 服务器将他们视
language DML)为一个单个整体或者一个逻辑工作单元
数据定义语言 (Data definition由单个的 DDL 语句组成
language DDL)
数据控制语言 (Data control由单个的 DCL 语句组成
language DCL)
数据库事务处理
::执行第一个DML SQL 语句时开始
::遇到下面事件之一结束:
一个COMMIT或ROLLBACK语句被发布
一个DDL 或DCL 语句执行(自动提交)
用户退出iSQL*Plus
系统崩溃
什么时候开始和结束一个事务?
当遇到第一个DML语句一个事务开始,当下面的情况发生时,事务结束:
:: 一个COMMIT或ROLLBACK语句被发布
:: 一个DDL语句,例如,CREATE被发布
:: 一个DCL语句被发布
:: 用户推出 iSQL*Plus
:: 机器失效或者系统崩溃
在一个事务结束以后,下一个可执行的SQL语句自动开始下一个事务。
一个DDL语句或者一个DCL语句自动提交,并且因此一个事务隐式结束。
COMMIT和ROLLBACK语句优点
用COMMIT和ROLLBACK语句,你能够:
::确保数据的一致性
::在数据永久改变之前进行预览
::分组逻辑相关的操作
全都是delet,insert,update语句.
时间
|commit ;
| <-------|
| transaction |
| delete |
| savepoint a |
| insert |
| |
| update |
| savepoint b |
| insert |
rollback
rollback to savepoint b,rollback to savepoint a .
语句说明
COMMIT结束当前事务,使得所有未决的数据永久改变。
SAVEPOINT name在当前事务中标记保存点。
ROLLBACK 结束当前事务,丢弃所有未决的数据改变。
ROLLBACK TO回滚当前事务到指定的保存点,从而丢弃保存点创建后的任何改变.
SAVEPOINT name如果忽略了 TO SAVEPOINT 子句,ROLLBACK 语句回滚整个事务。由于保存点是逻辑的,因此,没有办法列出已经创建的保存点。
发现了问题了没?DDL自动提交(commit)
SQL> commit;
提交完成。
SQL> create table a(name varchar2(20)) tablespace users;
表已创建。
SQL> savepoint a
2 ;
保存点已创建。
SQL> create table b (name varchar2(20)) tablespace users;
表已创建。
SQL> rollback to savepoint a;
rollback to savepoint a
*
ERROR 位于第 1 行:
ORA-01086: 从未创建保留点 'A'
SQL> rollback
2 ;
回退已完成。
SQL> desc b;
名称 是否为空? 类型
----------------------------------------- -------- -----------------
NAME VARCHAR2(20)
保存点不是方案对象,并且不能在数据字典中被引用。
回退改变到一个标记
::用SAVEPOINT语句在当前事务中创建一个标记
::用ROLLBACK TO SAVEPOINT语句回退到该标记
update..
savepoint update_done;
savepoint created.
insert...
rollback to update_done;
rollback complete.
回退到保存点
你能够在当前事务中用SAVEPOINT语句创建一个标记,它把事务分为较小的部分。你可以用ROLLBACK TO SAVEPOINT语句丢弃未决的改变到该标记。
如果你用与前面的保存点相同的名字创建了另一个保存点,哪个早一点时间创建的保存点就被删除了。
隐式事务处理
::在下面的情况下,一个自动提交发生:
DDL 语句被发送
DCL 语句被发送
正常退出iSQL*Plus,没有明确地发送COMMIT或ROLLBACK语句
::当iSQL*Plus 非正常退出时,或者发生系统故障时,一个自动回退发生.
状态详情
Automatic commitDDL 语句或 DCL 语句被发布。
iSQL*Plus 正常退出,不显式地发布 COMMIT 或 ROLLBACK 命令。
Automatic rollbackiSQL*Plus 异常终止,或系统故障。
注:在iSQL*Plus环境中可以用第三个命令。AUTOCOMMIT命令可以被触发或关闭。如果AUTOCOMMIT被设置为on,每个单个的DML语句在执行后被立即提交,你不能回滚所做的改变。如果AUTOCOMMIT被设置为off,COMMIT仍然能够被显式地发布。当DDL语句被发布时,或当你从iSQL*Plus退出时COMMIT语句被发布。(show autocommit,一般设置为off)
系统故障
当一个事务被系统故障中断时,整个事务被自动回滚。该回滚防止不必要的数据改变错误发生,并且返回表到他们上一次提交时的状态,以这种方式,Oracle服务器保护表的完整性。
在iSQL*Plus中,单击退出按钮,从会话正常的退出。在SQL*Plus中输入命令EXIT被时,窗口像正常退出一样关闭。
COMMIT或ROLLBACK之前数据的状态
::以前的数据状态能够被恢复
::当前用户能用SELECT语句查看DML 操作的结果
::其他用户不能观察当前用户DML 语句的结果
::受影响的行被锁定;其他用户不能改变受影响的行中数据
提交改变
在事务中所做的每一个数据改变在事务被提交之前都是临时的。
在COMMIT或ROLLBACK语句发布之前数据的状态:
:: 数据操纵操作首先影响数据库缓冲区,因此,数据以前的状态可以被恢复。
:: 当前用户可以查询表观察到数据操纵操作的结果。
:: 其他用户不能观察到当前用户所做的数据操纵操作的结果。Oracle服务器用读一致性来确保每个 用户看到的数据和上次提交时相同。
:: 受影响的行被锁定;其他用户不能改变受影响的行中的数据。
就Oracle服务器来说,数据的改变在事务被提交之前可能实际上已被写入数据库文件,但他们仍然是临时的。
如果许多用户同时对相同的表作了修改,那么,直到用户提交他们的修改之前,每个用户只能看到他自己的修改。
默认情况下,Oracle服务器有行级锁(row-level locking)。改变默认的锁机制是可能的。
在COMMIT之后数据的状态
用COMMIT语句使得未决的改变永久化.
::数据在数据库中被永久地改变.
::数据的以前状态被永久地丢失
::所有用户都能观察该结果
::受影响行的锁定被释放;其它用户可以操纵那些行
::所有保存点被擦除
提交改变
:产生改变
DELETE FROM employees
WHERE employee_id = 99999;
1 row inserted.
INSERT INTO departments
VALUES (290, 'Corporate Tax', NULL, 1700);
1 row inserted.
:提交改变(发布COMMIT语句,使得改变永久化)
COMMIT;
Commit complete.
ROLLBACK 后的数据状态
用ROLLBACK语句丢弃所有未决的改变:
::数据的改变被撤消
::数据的以前状态被恢复
::受影响行的锁定被释放
DELETE FROM copy_emp
22 rows deleted.
rollback;
rollback complete.
回退改变
用ROLLBACK语句放弃所有未决的改变,在一个ROLLBACK语句执行后:
:: 数据的改变被还原。
:: 数据以前的状态被恢复。
:: 受影响的行上的锁被释放。
例
在试图从TEST表中移除一条记录时,你可能意外地清空了整个表,你可以纠正这个错误,然后重新发布正确的语句,并且使得数据改变永久化。
DELETE FROM test;
25,000 rows deleted.
ROLLBACK;
Rollback complete.
DELETE FROM test
WHERE id = 100;
1 row deleted.
SELECT *
FROM test
WHERE id = 100;
No rows selected.
COMMIT;
Commit complete.
语句级Rollback
::如果一个单个的DML 语句在执行期间失败,仅仅该语句被回退
::Oracle 服务器实现一个隐式的保存点
::所有其他的改变被保留
::用户应该执行一个COMMIT或ROLLBACK语句来显式地结束事务
语句级回退
如果一个语句的执行错误被发现,一个事务的一部分可以用隐式的回退丢弃(只对这个语句失败了,什么也没有影响,对整个事务也没有.)。如果一个单个的DML语句在一个事务的执行期间失败,它的影响被一个语句级的回退撤消,但在事务中的以前已经由DML语句完成的改变不能丢弃,他们可以由用户显示地提交或回滚。(成功与失败都不影响)
/././././././././
Oracle在任何数据定义语言 (data definition language DDL) 语句之前和之后发布一个隐式的提交。所以,即使你的DDL语句执行不成功,你也不能回退前面的语句,因为服务器已经发布了提交命令。
执行COMMIT或ROLLBACK语句来明确地结束事务
Oracle服务器在数据上实现锁以防止对数据库中数据的并发操作,当某些事件发生时 (例如系统故障) 或当事务完成时,那些锁被释放。当一个DML语句成功执行时,数据库上的隐式锁被获得,默认情况下,Oracle服务器在尽可能的最低级别锁定数据。
执行带FOR UPDATE子句的LOCK TABLE语句或SELECT语句可以手动获得数据库表上的锁。
从Oracle9i开始,DBA有管理回退段的选择,或让Oracle自动管理在回退表空间中的回退数据。
读一致性
::读一致性在所有时间保证对数据的一致的观察
::一个用户所做的改变不与另一个用户所做的改变冲突
::读一致性确保下面的操作有同样的数据:
读者不等待写者
写者不等待读者
读一致性
数据库用户用两种方法访问数据库:
:: 读操作 (SELECT 语句)
:: 写操作 (插入、更新、删除 语句)
你需要读一致性,所以有下面事发生:
:: 数据库读者和写者被确保对数据观察的一致性。
:: 读者不能观察正在变化过程中的数据。
:: 写者被确保对数据库的改变以一致的方式进行。
:: 一个写者所做的改变不破坏另一个写者所做的改变或与其冲突。
读一致性的目的是确保每个用户看到的数据和他最后一次提交,并且在一个DML操作开始之前的数据一样。
读一致性的执行
读一致性的执行//好好体会,
读一致性是一种自动的执行,该操作在回退段保持一个数据库的局部的拷贝。
在对数据库进行一个插入、更新或者删除时,Oracle服务器在数据改变之前获得相关数据的拷贝,并且将这些数据写到一个回退段 (undo segment)。
所有读数据者,除了发布修改命令的用户,看到的数据还是改变之前的状态;他们看到的数据是回退段中的数据快照 (snapshot)。
在改变被提交到数据库之前,只有正在修改数据的用户能看见数据库的改变;除他之外的任何人看到的是回退段中的快照,这样就确保数据的读者读到一致的数据,而不是当前正在被修改的数据。
user A
update employees------->数据块
set salary=7000 |
where last_name='goyal';回退段
user B
select *-------> |<---数据块(已改变和未改变的数据)
from userA.employees; 读一致性映象| |
|<---回退段(改变以前的"旧的"数据)
当一个DML语句被提交时,对数据库所做的改变对任何执行SELECT语句的人成为可见的。在回退段中文件中被 "旧" 数据占用的空间被释放以重新使用。
如果事务被回滚,修改就被回退:
:: 在回退段中原来的,更旧的数据版本被写回到表中。
:: 所有用户看到的数据库就像事务开始之前那样。
当你提交一个事务时,Oracle服务器释放回滚信息,但并不立即销毁它,该信息保留在回退段中用来为事务提交之前就已经启动的查询创建相应数据的读一致查看。
锁定
在Oracle 数据库中,锁:
::在并发事务之间防止破坏性的交互作用
::不需要用户的动作
::自动使用最低的限制级别
::在事务处理期间保持
::有两种类型:显式锁定和隐式锁定
什么是锁?
锁是防止访问相同资源的事务之间的破坏性交互的机制。既可以是用户对象 (例如表或行),也可以是对用户不可见的系统对象 (例如共享数据结构和数据字典行)。
Oracle数据库怎样锁定数据
Oracle锁被自动执行,并且不要求用户干预。对于SQL语句隐式锁是必须的,依赖被请求的动作。隐式锁定除SELECT外,对所有的SQL语句都发生。
用户也可以手动锁定数据,这叫显式锁定。
隐式锁定
两种锁模式:
独占锁:不允许其他用户访问
共享所:允许其他用户访问
::高级数据并发操作:
DML: 表共享,行独占
查询: 不需要锁
DDL: 保护对象定义
::锁保持直到commit 或rollback
DML锁定
当执行数据操纵语言 (DML) 操作时,Oracle服务器通过DML锁防止数据被同时操纵。DML锁发生在两个级别:
:: 共享锁是在表级在DML操作期间自动获得的。用共享锁模式,几个事务可以在相同的资源上获得共享锁。
:: 对于用DML语句修改的每一行,独占锁被自动获得。独占锁在本事务被提交或被回滚之前防止行被其他事务修改。该锁确保无其他用户能够在相同的时间修改相同的行,并且覆盖另一个用户还没有提交的改变。
注:当你修改数据库对象 (例如表) 时,DDL 锁发生。
SELECT...FOR UPDATE语句也实现锁