Oracle - select AND delete in procedure

I need to return a set of rows from an Oracle procedure, and then delete them in the same procedure. Is there an easy way to do this without temporary tables? Perhaps something like a cursor in mind?

Basically, I get the entries out of the queue, and I want to avoid two round trips, because this is a very frequent process.

+3
source share
6 answers

Actually, you can do it without SELECT these days. You can simply DELETE the records that interest you and use the RETURNING clause to retrieve these records into a local variable as they are deleted.

DELETE FROM my_table
  WHERE <whatever conditions>
  RETURNING column1, column2, ...
  INTO array1, array2, ...

, . . , , .

+8

,

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;
+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 left after the procedure completed
*/


        ID VALUE
---------- --------------------------------------------------
         2 Value 2
+3

TYPE ?

.

CREATE TYPE blah as (data-columns-go-here)
/

CREATE TYPE blah_table AS TABLE OF blah;
/
+2

reubenpeeris cagcowboy 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;

Edit: I believe this will also work with the stored procedure if you provide the popped_records_table_type instance as an IN / OUT parameter:

PROCEDURE pop_records(popped_records IN OUT popped_records_table_type, ...) IS
    -- Pretty much the same as above
+2
source

There is something in Oracle that causes extended queuing, it might be better to use this function than to create your own queuing system.

0
source

Source: https://habr.com/ru/post/1708149/


All Articles