Defining a stored procedure is one SQL statement; running it is another. CREATE PROCEDURE registers the name, parameters, and (for native DB2 SQL) the SQL PL body and bind options. ALTER PROCEDURE adds or replaces versions. DROP PROCEDURE removes the object. CALL is how every client — COBOL, JDBC, SPUFI, another procedure — invokes it.
There are separate CREATE PROCEDURE forms in the SQL Reference: SQL native, SQL external (deprecated), and external (host language). This page emphasises native SQL, then shows an external skeleton.
Authorization typically includes SYSADM, system DBADM, or CREATEIN on the schema. The schema qualifier must be allowed for the owner. WLM ENVIRONMENT FOR DEBUG MODE also needs RACF authority on that application environment.
123456789101112131415161718CREATE PROCEDURE HR.RAISE_SALARY (IN P_EMPNO CHAR(6), IN P_RATE DECIMAL(6,2)) LANGUAGE SQL MODIFIES SQL DATA DYNAMIC RESULT SETS 0 COMMIT ON RETURN NO QUALIFIER HR ASUTIME LIMIT 10000 BEGIN UPDATE EMP SET SALARY = SALARY * (1 + P_RATE) WHERE EMPNO = P_EMPNO; IF SQLCODE <> 0 THEN SIGNAL SQLSTATE '75001' SET MESSAGE_TEXT = 'Raise failed'; END IF; END
When VERSION is omitted and the procedure does not exist, Db2 creates the initial version V1 and binds a package using the options on the statement (QUALIFIER, CURRENT DATA, DYNAMICRULES, EXPLAIN, SQL PATH, and the rest of the option-list).
| Option | Meaning |
|---|---|
| LANGUAGE SQL | Native SQL PL body (omit EXTERNAL/FENCED) |
| MODIFIES / READS / CONTAINS SQL | How much SQL the body may run |
| DYNAMIC RESULT SETS n | Max cursors left open for the client (default 0) |
| COMMIT ON RETURN | NO (default), YES, or AUTONOMOUS |
| ASUTIME LIMIT | Cancel if the CALL exceeds CPU service units |
| VERSION | Version id; omit on first CREATE for V1 |
MODIFIES SQL DATA allows INSERT/UPDATE/DELETE. READS SQL DATA allows SELECT but not changes. CONTAINS SQL is even tighter (no read or modify of table data). Db2 checks nested routines against this specification.
CALLED ON NULL INPUT is the native SQL behaviour: the procedure is still called if parameters are null. All parameters are nullable.
External form (body not in the statement):
123456789101112131415CREATE PROCEDURE APP.SUMMOD (IN V1 INTEGER, OUT V2 CHAR(9)) LANGUAGE C DETERMINISTIC NO SQL EXTERNAL NAME SUMMOD COLLID SUMCOLL ASUTIME LIMIT 900 PARAMETER STYLE GENERAL WITH NULLS STAY RESIDENT NO WLM ENVIRONMENT PAYROLL PROGRAM TYPE MAIN SECURITY DB2 DYNAMIC RESULT SETS 10 COMMIT ON RETURN NO;
Native SQL ALTER is how you version:
123456789101112ALTER PROCEDURE TEST.UPDATE_BALANCE REPLACE VERSION V2 (IN CUSTOMER_NO INTEGER, IN AMOUNT DECIMAL(9,2)) MODIFIES SQL DATA ASUTIME LIMIT 100 BEGIN UPDATE ACCOUNTS SET BAL = BAL + AMOUNT WHERE CUSTNO = CUSTOMER_NO AND CUSTSTAT = 'A'; END
Function level 507: CREATE OR REPLACE PROCEDURE … VERSION V2 adds V2 if missing or replaces it if present. CREATE OR REPLACE without VERSION replaces the procedure definition (privileges on the procedure are kept).
External ALTER changes LANGUAGE, WLM ENVIRONMENT, EXTERNAL NAME, DYNAMIC RESULT SETS, and similar — not an SQL PL body.
1DROP PROCEDURE HR.RAISE_SALARY RESTRICT;
DROP removes the procedure from the catalog, including versions. Packages for native SQL go away with it. Callers fail until you recreate. Prefer DROP VERSION when you only want to retire an old native version. Do not confuse DROP with -STOP PROCEDURE, which only blocks scheduling.
CALL invokes the procedure. Arguments must be compatible types. The defined encoding scheme of a parameter comes from CREATE PROCEDURE (or the subsystem default).
12345678910CALL HR.RAISE_SALARY('000010', 0.05); -- Embedded SQL (host variables) -- EXEC SQL CALL HR.RAISE_SALARY (:HV-EMPNO, :HV-RATE); -- Procedure name in a host variable -- EXEC SQL CALL :PROCNM (:HV-EMPNO, :HV-RATE); -- SQLDA -- EXEC SQL CALL HR.RAISE_SALARY USING DESCRIPTOR :SQLDA;
Simple CALL with literals works in SPUFI/CLP for IN parameters. OUT and INOUT need host variables (or JDBC parameter markers) so Db2 has somewhere to return values.
Nested CALL: a procedure may CALL another. Recursion is possible but must be bounded (ASUTIME helps). Do not assume Language Environment variables persist between external CALLs — another user’s procedure or another SPAS may run in between.
If an external procedure abends enough times (STOP AFTER n FAILURES or subsystem MAX ABEND COUNT), Db2 stops it (STOPABN on that member in data sharing). Other members may still run it. Fix the abend, then START PROCEDURE.
Native SQL: CALL uses the active version unless you specify a version or SET CURRENT ROUTINE VERSION. That register is covered with operations and debugging. BIND DEPLOY copies a version to another subsystem — a promotion path instead of shipping COBOL loadlibs.
CREATE PROCEDURE is writing the recipe card and pinning it on the kitchen board (and Db2 secretly prints a package cookbook). ALTER is taping a new revision on the card, or adding a second card labelled V2 and later saying “cook from V2.” DROP throws the cards away. CALL is shouting the dish name through the window. COMMIT ON RETURN YES is the kitchen also ringing up the bill when the plate comes out. STOP PROCEDURE is a “closed” sign; the recipes are still in the drawer.
1. CREATE PROCEDURE for a native SQL procedure implicitly:
2. CALL invokes:
3. DROP PROCEDURE:
4. COMMIT ON RETURN YES means:
5. Parameter types on CALL must be: