CREATE PROCEDURE archive_old_orders(cutoff date)LANGUAGE plpgsql AS $BEGIN INSERT INTO orders_archive SELECT * FROM orders WHERE placed_at < cutoff; DELETE FROM orders WHERE placed_at < cutoff; COMMIT;END $;
2. Calling Procedure
CALL archive_old_orders('2024-01-01');
3. Using Transaction Control
CREATE PROCEDURE batch_process() LANGUAGE plpgsql AS $BEGIN LOOP WITH batch AS (SELECT id FROM queue LIMIT 1000 FOR UPDATE SKIP LOCKED) DELETE FROM queue WHERE id IN (SELECT id FROM batch); EXIT WHEN NOT FOUND; COMMIT; END LOOP;END $;
Allowed In Procedure
Allowed In Function
COMMIT, ROLLBACK
No (read-only TX context)
4. Using Parameters
Mode
Notes
IN
Input (default)
OUT
Return values via CALL
INOUT
Both
CREATE PROCEDURE inc_count(INOUT cnt int) LANGUAGE plpgsql AS $BEGIN cnt := cnt + 1; END $;CALL inc_count(5); -- returns 6
5. Using Exceptions in Procedures
BEGIN ...EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE;END;
Note: Inside an EXCEPTION block, you cannot issue COMMIT/ROLLBACK that spans the outer subtransaction; PL uses implicit savepoints.
6. Replacing Procedure
CREATE OR REPLACE PROCEDURE archive_old_orders(cutoff date) ...
7. Listing Procedures
\df+ schema.*SELECT proname FROM pg_proc WHERE prokind = 'p'; -- procedures only
8. Dropping Procedure
DROP PROCEDURE IF EXISTS archive_old_orders(date);