我需要从Oracle过程返回一个rowset,然后在同一过程中删除它们。有没有临时表这样做的简洁方法?像内存中的游标那样的东西?
基本上我把队列中的记录弹出来了,我想避免两次往返,因为这是一个非常频繁的过程。
答案 0 :(得分:8)
实际上,这些天你可以在没有SELECT的情况下完成。您可以简单地删除您感兴趣的记录,并使用RETURNING子句将这些记录删除为局部变量。
DELETE FROM my_table
WHERE <whatever conditions>
RETURNING column1, column2, ...
INTO array1, array2, ...
此方法稍微令人讨厌的部分是您需要将每个列提取到单独的变量中。您不能在此上下文中使用记录类型。所以,如果你有很多专栏,它会变得很麻烦。
答案 1 :(得分:3)
您可以使用光标进行更新,例如
DECLARE
CURSOR c_updates
IS
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.field = t2.field
WHERE t2.field IS NULL
FOR UPDATE OF t1.field;
l_record c_updates%ROWTYPE;
BEGIN
OPEN c_updates;
LOOP
FETCH c_updates INTO l_record;
EXIT WHEN c_updates%NOTFOUND;
--Do what you want with l_record
DELETE FROM table1
WHERE CURRENT OF c_updates;
END LOOP;
CLOSE c_updates;
END;
答案 2 :(得分:3)
您可以从过程或匿名块返回游标:
BEGIN
OPEN :cur FOR
SELECT *
FROM table
WHERE condition;
DELETE
FROM table
WHERE condition;
END;
删除后光标将保持不变。
请参阅我博客中的条目以获取详细说明:
,简而言之就是这个条目:
CREATE TABLE t_deleter (id INT NOT NULL PRIMARY KEY, value VARCHAR2(50))
/
INSERT
INTO t_deleter (id, value)
VALUES (1, 'Value 1')
/
INSERT
INTO t_deleter (id, value)
VALUES (2, 'Value 2')
/
COMMIT
/
SELECT *
FROM t_deleter
/
VAR cur REFCURSOR
BEGIN
OPEN :cur FOR
SELECT *
FROM t_deleter
WHERE id = 1;
DELETE
FROM t_deleter
WHERE id = 1;
END;
/
PRINT cur
SELECT *
FROM t_deleter
/
Table created.
1 row created.
1 row created.
Commit complete.
ID VALUE
---------- --------------------------------------------------
1 Value 1
2 Value 2
PL/SQL procedure successfully completed.
/*
PRINT CUR
This is what returned to the client
*/
ID VALUE
---------- --------------------------------------------------
1 Value 1
/*
SELECT *
FROM t_deleter
This is what's left after the procedure completed
*/
ID VALUE
---------- --------------------------------------------------
2 Value 2
答案 3 :(得分:2)
将数据填充到TYPE中并返回?
e.g。
CREATE TYPE blah as (data-columns-go-here)
/
CREATE TYPE blah_table AS TABLE OF blah;
/
答案 4 :(得分:2)
以reubenpeeris' answer和cagcowboy's answer:
为基础警告:目前我无法访问PL / SQL编译器,因此可能出现问题。
TYPE popped_records_table_type IS TABLE OF my_table%ROWTYPE INDEX BY BINARY_INTEGER;
FUNCTION pop_records(...) RETURN popped_records_table_type IS
popped_records popped_records_table_type;
popped_record my_table%ROWTYPE;
next_popped_record_index BINARY_INTEGER;
CURSOR popped_records_cursor IS
SELECT * FROM my_table WHERE ... FOR UPDATE;
BEGIN
next_popped_record_index := 1;
OPEN popped_records_cursor;
LOOP
FETCH popped_records_cursor INTO popped_record;
EXIT WHEN popped_records_cursor%NOTFOUND;
DELETE FROM my_table WHERE CURRENT OF popped_records_cursor;
popped_records(next_popped_record_index) := popped_record;
next_popped_record_index := next_popped_record_index + 1;
END LOOP;
CLOSE popped_records_cursor;
RETURN popped_records;
END;
编辑:我相信这也适用于存储过程,只要你提供popped_records_table_type的实例作为IN / OUT参数:
PROCEDURE pop_records(popped_records IN OUT popped_records_table_type, ...) IS
-- Pretty much the same as above
答案 5 :(得分:0)
Oracle有一些调用高级排队的东西,也许最好使用该功能而不是构建自己的排队系统。