Oracle - 在过程中选择并删除

时间:2009-05-12 08:07:24

标签: oracle plsql

我需要从Oracle过程返回一个rowset,然后在同一过程中删除它们。有没有临时表这样做的简洁方法?像内存中的游标那样的东西?

基本上我把队列中的记录弹出来了,我想避免两次往返,因为这是一个非常频繁的过程。

6 个答案:

答案 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' answercagcowboy'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有一些调用高级排队的东西,也许最好使用该功能而不是构建自己的排队系统。