By default, a procedure will execute as part of a larger transaction owned by the session. As the documentation mentions:
Note: A transaction can span multiple blocks, and a block can contain multiple transactions.
With your code as outlined, no other session will see your delete or insert until you commit after calling the procedure. If you just execute it from an SQL*Plus prompt for example:
SQL> exec loadDenormalizedTable;
PL/SQL procedure successfully completed.
SQL>
... then anybody else looking at the table will still see the old data, even after both the delete and insert have completed. (Anyone else trying to execute the procedure, or insert or delete data in denormalizedTable
, will block, but presumably you're only expecting others to be querying it). Once you issue a commit
then everyone will see the same thing.
The only way to get the behaviour you describe is to manually end the transaction within the procedure:
CREATE OR REPLACE PROCEDURE loadDenormalizedTable IS
BEGIN
DELETE FROM denormalizedTable;
COMMIT WORK; -- makes the delete visible elsewhere
INSERT INTO
denormalizedTable
(
data
)
SELECT DISTINCT
data
FROM
normalizedTables;
END;
/
You do not not need to commit
in the middle of the procedure, and it's very rare that you would or should ever want to do that as it breaks the atomicity.
It's possible you're doing something that does an implicit commit without you realising it; maybe calling another procedure or function that does its own commit (one of the reasons not to do that - it can have unexpected side-effects!), or perhaps a DDL statement - which will always do an implicit commit behind the scenes, but you'd have to be doing that with dynamic SQL anyway.
One other possibility is that you aren't actually doing a delete
, but that you are doing a truncate
. That would be visible to everyone else immediately, without an explicit commit, as hinted at in the documentation. That would also be a significant departure from the outline you provided though.