我有一个任务表,其中有3列(id,TimeStamp,Is_procssed)。我在Oracle中创建了一个存储过程,如下所示。
CREATE OR REPLACE PROCEDURE AUDITING.fetchTasksByTimestamp(
p_timestamp IN TIMESTAMP,
p_limit IN NUMBER,
updated_ids OUT SYS_REFCURSOR
) IS
TYPE NumberTableType IS TABLE OF tasks.id%TYPE;
l_updated_ids NumberTableType;
BEGIN
-- Select the IDs of the records to be updated in a thread-safe manner
SELECT id BULK COLLECT INTO l_updated_ids
FROM tasks
WHERE is_processed = 0
AND timestamp_column <= p_timestamp
FOR UPDATE SKIP LOCKED;
-- Limit the number of records using p_limit
-- IF l_updated_ids.COUNT > p_limit THEN
-- l_updated_ids.DELETE(p_limit + 1, l_updated_ids.COUNT);
-- END IF;
--
-- -- If no records are found, return an empty cursor
-- IF l_updated_ids.COUNT = 0 THEN
-- OPEN updated_ids FOR SELECT * FROM DUAL WHERE 1=0; -- Empty result set
-- RETURN;
-- END IF;
-- Update the tasks that were locked
for indx in l_updated_ids loop
UPDATE tasks SET is_processed = 1 WHERE id = l_updated_ids(indx);
END LOOP;
-- Open the updated_ids cursor for the collected IDs
-- OPEN updated_ids FOR
-- SELECT * FROM TABLE(l_updated_ids);
COMMIT;
END fetchTasksByTimestamp;
字符串
以上给出了编译时的错误:“29/17 PLS-00456:项目'L_MANATED_IDS'不是游标”。
我的要求是在多线程环境中从java spring Boot 调用上面的存储过程。由于部署了多个示例,并且有一个cron将调用SP。我希望每个线程都能获得不同的记录列表。因此我也使用了skip locked。
但是上面的SP正在返回更新的行列表。我尝试了各种方法,但无法解决。
如果有人能帮我解决这个问题,那就太好了。
1条答案
按热度按时间xhv8bpkk1#
您不能在SQL中使用本地PL/SQL集合(直到Oracle 23),并且需要在SQL作用域中定义一个集合。
字符串
您还可以使用
UPDATE ... RETURNING ... BULK COLLECT INTO ...
简化问题。型
给定样本数据:
型
然后:
型
产出:
型
COMMIT
,因为它会阻止你将多个过程链接在一起,如果在后面的过程中出现错误,那么ROLLBACK
就会将它们全部删除。相反,你应该在用于调用过程的代码中使用COMMIT
。*id
s更新时,您的代码没有指定ORDER BY
子句;这里返回前5个只是巧合,如果没有ORDER BY
子句,可以以任何顺序获取行。fiddle
或者:
型
fiddle的