FOR UPDATE NOWAIT语句:有的时候我们打开一个游标是为了更新或者删除一些记录,这种情况下我们希望 在打开游标的时候即锁定相关记录,应该使用for update nowait语句,倘若锁定失败我们就停止不再继续,以免 出现长时间等待资源的死锁情况。或者仅仅想想修改某一个记录,在update前,也可以select ....where ..... for update nowait 一下 锁定要修改的记录。
SELECT ...
FROM ...
FOR UPDATE [OF column_reference][NOWAIT];
举例1:
DECLARE
CURSOR sal_cursor IS
SELECT e.department_id, employee_id, last_name, salary
FROM employees e, departments d
WHERE d.department_id = e.department_id
and d.department_id = 60
FOR UPDATE OF salary NOWAIT;
BEGIN
FOR emp_record IN sal_cursor
LOOP
IF emp_record.salary < 5000 THEN
UPDATE employees
SET salary = emp_record.salary * 1.10
WHERE CURRENT OF sal_cursor;
END IF;
END LOOP;
END;
举例2:
PROCEDURE upd_sal(p_job_id VARCHAR,
p_min_salary NUMBER,
p_max_salary NUMBER) IS
e_salary EXCEPTION;
v_job_id VARCHAR2(32);
e_resource_busy EXCEPTION;
PRAGMA EXCEPTION_INIT(e_resource_busy,
-54);
BEGIN
IF p_max_salary < p_min_salary THEN
RAISE e_salary;
END IF;
SELECT jobs.job_id
INTO v_job_id
FROM jobs
WHERE jobs.job_id = p_job_id
FOR UPDATE OF min_salary NOWAIT; --这里上锁
UPDATE jobs
SET jobs.min_salary = p_min_salary,
jobs.max_salary = p_max_salary
WHERE jobs.job_id = p_job_id;
EXCEPTION
WHEN e_salary THEN
dbms_output.put_line('max_salary < min_salary');
raise_application_error(-20001,
'max_salary < min_salary');
WHEN no_data_found THEN
dbms_output.put_line('no this job id');
raise_application_error(-20001,
'no this job id');
WHEN e_resource_busy THEN --表记录被锁时也可以捕获
raise_application_error(-20001,
'表记录被锁');
/*WHEN OTHERS THEN
dbms_output.put_line('表被锁');*/
END;