oracle我希望从表中随机选择几行,更新这些行中的列并使用存储过程返回它们
PROCEDURE getrows(box IN VARCHAR2, row_no IN NUMBER, work_dtls_out OUT dtls_cursor) AS
v_id VARCHAR2(20);
v_workname VARCHAR2(20);
v_status VARCHAR2(20);
v_work_dtls_cursor dtls_cursor;
BEGIN
OPEN v_work_dtls_cursor FOR
SELECT id, workname, status
FROM item
WHERE status IS NULL
AND rownum <= row_no
FOR UPDATE;
LOOP
FETCH v_work_dtls_cursor
INTO v_id ,v_workname,v_status;
UPDATE item
SET status = 'started'
WHERE id=v_id;
EXIT
WHEN v_work_dtls_cursor % NOTFOUND;
END LOOP;
close v_work_dtls_cursor ;
/* I HAVE TO RETURN THE SAME ROWS WHICH I UPDATED NOW.
SINCE CURSOR IS LOOPED THRU, I CANT DO IT. */
END getrows;
请帮助
答案 0 :(得分:1)
跟进Sjuul Janssen的出色建议:
create type get_rows_row_type as object
(id [item.id%type],
workname [item.workname%type],
status [item.status%type]
)
/
create type get_rows_tab_type as table of get_rows_row_type
/
create function get_rows (box in varchar2, row_no in number)
return get_rows_tab_type pipelined
as
v_work_dtls_cursor dtls_cursor;
l_out_rec get_rows_row_type;
BEGIN
OPEN v_work_dtls_cursor FOR
SELECT id, workname, status
FROM item sample ([ROW SAMPLE PERCENTAGE])
WHERE status IS NULL
AND rownum <= row_no
FOR UPDATE;
LOOP
FETCH v_work_dtls_cursor
INTO l_out_rec.id, l_out_rec.workname, l_outrec.status;
EXIT WHEN v_work_dtls_cursor%NOTFOUND;
UPDATE item
SET status = 'started'
WHERE id=l_out_rec.id;
l_out_rec.id.status := 'started';
PIPE ROW (l_out_rec);
END LOOP;
close v_work_dtls_cursor ;
END;
/
一些注意事项:
这是未经测试的。
您需要使用适当的模式类型替换类型声明中的括号部分。
您需要在SELECT语句的SAMPLE子句中提供适当的值;有可能将其作为参数传递,但可能需要使用动态SQL。但是,如果您的要求是从表中获取随机行 - 只是按ROWNUM过滤将无法完成 - 您将需要执行类似的操作。
因为您正在选择FOR UPDATE,所以一个会话可以阻止另一个会话。如果你是11g,你可能希望检查SELECT语句的SKIP LOCKED子句,这将使多个并发会话能够运行这样的代码。
答案 1 :(得分:0)
不知道你在做什么提交,但根据代码,你需要做的就是SELECT ... FROM ITEM WHERE STATUS ='started'
如果是小数字,您可以保留ROWID的集合。 如果它更大,那么我会做一个
INSERT into a global temporary table SELECT id FROM item .. AND ROWNUM < n;
UPDATE item SET status = .. WHERE id in (SELECT id FROM global_temp_table);
然后返回
的光标SELECT ... FROM item WHERE id in (SELECT id FROM global_temp_table);
答案 2 :(得分:0)
也许这可以帮助你做你想做的事情?
答案 3 :(得分:0)
可能的解决方案:
create type nt_number as table of number;
PROCEDURE getrows(box IN VARCHAR2,
row_no IN NUMBER,
work_dtls_out OUT dtls_cursor) AS
v_item_rows nt_number;
indx number;
cursor cur_work_dtls_cursor is
SELECT id
FROM item
WHERE status IS NULL
AND rownum <= row_no
FOR UPDATE;
BEGIN
open cur_work_dtls_cursor;
fetch cur_work_dtls_cursor bulk collect into nt_number;
for indx in 1 .. item_rows.count loop
UPDATE item
SET status = 'started'
WHERE id=v_item_rows(indx);
END LOOP;
close cur_work_dtls_cursor;
open work_dtls_out for select id, workname, status
from item i, table(v_item_rows) t
where i.id = t.column_value;
END getrows;
如果行数特别大,全局临时解决方案可能会更好。