Wednesday 14 September 2011

BULK COLLECT and FOR UPDATE OF A Fine Match

Question:

Can I bulk collect using the FOR UPDATE OF clause in a SELECT statement? For example:
SELECT *
BULK COLLECT INTO l_employee
FROM employee
FOR UPDATE OF employee
ORDER BY last_name
Or in other words: I want to ensure that nobody updates the selected records while I run the BULK COLLECT process. Without BULK COLLECT, the FOR UPDATE OF clause will do the job.
I read somewhere that FOR UPDATE was not allowed in BULK COLLECT. Is that accurate?

Answer:

Luis, you certainly can include a FOR UPDATE OF clause in a BULK COLLECT query. The following script demonstrates. If you run all the code up through the first anonymous block in one session, and then run the UPDATE statement at the end in a second session, you will find that this UPDATE is blocked until the first session completes its changes and COMMITs.
Note: you will need EXECUTE privileges on DBMS_LOCK, as I use its SLEEP procedure to pause the block long enough to give you the opportunity to run the last UPDATEZ statement in the second session.
REM Run in first session...

DROP TABLE test_table;
CREATE TABLE test_table (name VARCHAR2(100), description VARCHAR2(1000));
INSERT INTO test_table VALUES ('GEORGIE', 'Handsome fellow');
INSERT INTO test_table VALUES ('PAULA', 'Sharp as a tack');
COMMIT;

DECLARE
TYPE test_table_tc IS TABLE OF test_table.description%TYPE
INDEX BY PLS_INTEGER;

l_list test_table_tc;
BEGIN
SELECT description
BULK COLLECT INTO l_list
FROM test_table
FOR UPDATE OF name;

DBMS_LOCK.SLEEP (30);

FORALL indx IN l_list.FIRST .. l_list.LAST
UPDATE test_table SET name = l_list(indx);

COMMIT;
END;
/

REM Run in second session within 30 seconds....

BEGIN
UPDATE test_table SET name = 'PORGIE'
WHERE name = 'GEORGIE';
END;
/

No comments:

Post a Comment