更新光标的列,然后使用该值进行选择
我有一个查询这样的表的游标
CURSOR Cur IS
SELECT Emp_No,status
from Employee
FOR UPDATE OF status;
现在我想使用 Emp_no 从另一个表更新 Employee 表中的状态。完成此操作后,我需要使用此状态来调用自定义业务逻辑,而不是游标检索到的原始状态。解决这个问题的最佳方法是什么?这是我写的。我顺便声明了一个名为 v_status 的变量,
FOR Rec IN Cur LOOP
BEGIN
UPDATE Employee
SET status = (select a.status from Employee_Status where a.Emp_No = rec.Emp_No)
WHERE CURRENT OF Cur ;
COMMIT;
END;
SELECT status INTO v_status
FROM Employee
where Emp_No = rec.Emp_No;
IF(v_status = 'Active') THEN
-- Custom Business Logic
ELSE
-- Business logic
END IF;
END LOOP;
实现此目的的更好方法是什么?
I have a cursor that queries a table like this
CURSOR Cur IS
SELECT Emp_No,status
from Employee
FOR UPDATE OF status;
Now I would want to update my status in Employee table from another table using the Emp_no. Once I have done this I need to use this status for calling custom business logic and not the original status retrieved by the cursor. What is the best way of going about this? Here is what I have written. I declared a variable called v_status by the way
FOR Rec IN Cur LOOP
BEGIN
UPDATE Employee
SET status = (select a.status from Employee_Status where a.Emp_No = rec.Emp_No)
WHERE CURRENT OF Cur ;
COMMIT;
END;
SELECT status INTO v_status
FROM Employee
where Emp_No = rec.Emp_No;
IF(v_status = 'Active') THEN
-- Custom Business Logic
ELSE
-- Business logic
END IF;
END LOOP;
What would be a better way to achieve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
1)我希望在您的实际代码中,您的循环中间没有
COMMIT
。由于提交会释放事务持有的锁,因此使用FOR UPDATE
子句取出的行级锁将被释放,其他会话可以自由更新相同的行。在 Oracle 的更高版本中,如果执行此操作,您将收到“ORA-01002: fetch out of order”错误。在早期版本的 Oracle 中,此错误被忽略,这会导致偶尔出现不正确的结果。2) 您是否需要逐行更新
EMPLOYEE
表?我倾向于将更新移到循环之外,以便最大限度地利用 SQL,因为这是处理数据的最有效方法。如果您的业务逻辑适合它,我还建议执行批量操作以将数据获取到业务逻辑可以迭代的本地集合中,以便最大限度地减少 SQL 和 PL/SQL 之间的上下文转换。因此,根据您的评论,在您的示例中,光标的定义中应该有一个谓词,对吗?像这样的东西吗?
如果是这样,您需要在单个 UPDATE 语句中使用相同的谓词(可能而不是
EXISTS
子句)。但由于您知道您只想处理 UPDATE 语句影响的行,因此您可以将这些行返回到本地集合中1) I'm hoping in your real code that you don't have a
COMMIT
in the middle of your loop. Since committing releases the locks held by your transaction, the row-level locks taken out with theFOR UPDATE
clause are released and other sessions are free to update the same rows. In later versions of Oracle, you'll get an "ORA-01002: fetch out of sequence" if you do this. In earlier versions of Oracle, this error was ignored which lead to occasionally incorrect results.2) Do you need to update the
EMPLOYEE
table on a row-by-row basis? I'd tend to move the update outside of the loop in order to maximize SQL since that's the most efficient way to process data. If your business logic is amenable to it, I'd also suggest doing bulk operations to fetch the data into local collections that your business logic can iterate through in order to minimize context shifts between SQL and PL/SQL.So, based on your comments, in your example, there should be a predicate in the definition of your cursor, right? Something like this?
If so, you'd need that same predicate in the single UPDATE statement (potentially instead of the
EXISTS
clause). But since you know that you only want to process the rows that your UPDATE statement affected, you can just return those rows into a local collection为什么不简单地:
Why not just simply:
您可以使用 RETURNING 子句:
You could use the RETURNING clause: