pl / sql如何使用带有游标的for循环进行更新操作
Posted
技术标签:
【中文标题】pl / sql如何使用带有游标的for循环进行更新操作【英文标题】:pl/sql How to use for loop with cursor for update operation 【发布时间】:2015-07-01 21:35:27 【问题描述】:我是 PL/SQL 的新手,在一本书中我发现了这个关于更新游标的示例
declare
cursor c_grade(i_student_id in enrollment.student_id%type,
i_section_id in enrollment.section_id%type
) is
select FINAL_GRADE
from enrollment
where student_id_id = i_student_id
and section_id = i_section_id
for update;
cursor c_enrollment is
select e.student_id, e.section_id
from enrollment enr, section sec
where sec.course_no = 135 and
enr.section_id = sec_section_id;
begin
for r_enroll in c_enrollment loop
for r_grade in c_grade(r_enroll.student_id. r_enroll.section_id) loop
update enrollment
set final_grade = 90
where student_id = r_enroll.student_id
and section_id = r_enroll.section_id;
end loop;
end loop;
end;
我的问题是为什么我需要在这个例子中使用 for update 游标?与此相比有什么好处:
for r_enroll in c_enrollment loop
update enrollment
set final_grade = 90
where student_id = r_enroll.student_id
and section_id = r_enroll.section_id;
end loop;
【问题讨论】:
for update lock(protect) rows and other transaction can't change the same rows 【参考方案1】:正如评论中提到的,FOR UPDATE 子句用于锁定 SELECT 语句中的行,这样在锁定之前没有其他用户能够更改这些行(更新、删除等)释放。
一旦您发出 COMMIT 或 ROLLBACK 语句,锁通常会自动释放。当有大量 DML 语句在来自不同用户的同一组数据上运行时,这特别有用。例如,您需要在某个时刻更新 ID 最高的行,但在更新该行之前,另一行已被不同的用户更新为 ID 较高的行。
对于您的示例,使用
for r_grade in c_grade(r_enroll.student_id. r_enroll.section_id) loop
保证你更新的是你锁定的版本,在你之前没有其他人更新过。
您可以通过示例here找到详细说明
【讨论】:
【参考方案2】:为了详细说明您的问题,Oracle 中有两种类型的锁定机制
1) Pessimistic Locking
2) Optimistic Locking
Optimistic locking is generally implemented by developers in the code some timestamp etc phenomena so that at one time only one user at a time can update a particular record.
Pessimistic locking on the other hand (what you have used in the question) is the inbuilt functionality your database is providing to handle locking mechanism automatically.
Let me know if this clears your doubt on this.
【讨论】:
以上是关于pl / sql如何使用带有游标的for循环进行更新操作的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PL/SQL 代码的 for 循环中创建游标并将结果批量收集到表中
为啥我们不需要在 pl sql 的 for 循环中打开和获取显式游标?