SQL PL is the language; native SQL procedures and SQL functions are the objects you hang that language on. This page compares native SQL procedures, compiled SQL scalar functions, inlined SQL scalar functions, and SQL table functions in DB2 for z/OS: how you CREATE them, how you invoke them, whether a package exists, and which SQL PL features each body may use.
| Object | How you run it | Package? |
|---|---|---|
| Native SQL procedure | CALL | Yes — bound at CREATE/ALTER |
| Compiled SQL scalar function | In expressions | Yes |
| Inlined SQL scalar function | In expressions | No — body folded into the query |
| SQL table function | TABLE(fn(args)) in FROM | No — RETURN query is inlined |
External procedures and external UDFs (COBOL, C, Java) are not SQL PL; they have a LANGUAGE other than SQL and an EXTERNAL NAME. Sourced functions wrap another function and have no SQL PL body. This page stays on LANGUAGE SQL.
CREATE PROCEDURE (SQL — native) registers a routine whose body is SQL PL. IBM transforms that body into a program and binds a package. First CREATE makes version V1 unless you specify VERSION. ALTER PROCEDURE ADD/REPLACE VERSION and ACTIVATE VERSION are how shops roll out logic without renaming the CALL.
12345678910111213141516CREATE PROCEDURE HR.GIVE_RAISE (IN P_EMPNO CHAR(6), IN P_PCT DECIMAL(5,2), OUT P_NEWSAL DECIMAL(9,2)) LANGUAGE SQL MODIFIES SQL DATA DETERMINISTIC COMMIT ON RETURN NO BEGIN UPDATE DSN8C10.EMP SET SALARY = SALARY * (1 + P_PCT / 100) WHERE EMPNO = P_EMPNO; SELECT SALARY INTO P_NEWSAL FROM DSN8C10.EMP WHERE EMPNO = P_EMPNO; END
Invoke with CALL HR.GIVE_RAISE(:HV-EMP, :HV-PCT, :HV-NEW). Nested CALL is how SQL PL procedures reuse each other. Nested and recursive CALL share the same depth limit.
Compared with external SQL procedures (deprecated): native SQL lives in the catalog and package; you do not precompile a generated C program. New work should be native.
An SQL scalar function returns one value per invocation. The body is SQL PL. Db2 distinguishes inlined and compiled scalar functions from the CREATE FUNCTION text.
If the definition is a simple RETURN expression, Db2 can inline that expression into the statement that called the function. There is no separate package to EXPLAIN as a routine. That is fast and simple — and limited. You do not get a full compound with handlers and loops.
1234567CREATE FUNCTION HR.YR_SAL (P_SAL DECIMAL(9,2)) RETURNS DECIMAL(11,2) LANGUAGE SQL DETERMINISTIC CONTAINS SQL NO EXTERNAL ACTION RETURN P_SAL * 12;
Use inlined scalars for formulas you want in many queries without repeating the arithmetic. If you later add BEGIN, IF, or other enhanced CREATE FUNCTION features, Db2 creates a compiled function instead.
Compiled SQL scalar functions support the larger SQL PL statement set: compound statements, IF, loops, GET DIAGNOSTICS, and an enhanced RETURN that can reference a scalar fullselect. A package is generated. Each invocation runs that package (one or more times).
12345678910111213141516CREATE FUNCTION HR.REVERSE_STR (INSTR VARCHAR(100)) RETURNS VARCHAR(100) LANGUAGE SQL DETERMINISTIC CONTAINS SQL NO EXTERNAL ACTION BEGIN DECLARE I INT; DECLARE REV VARCHAR(100) DEFAULT ''; SET I = LENGTH(INSTR); WHILE I > 0 DO SET REV = REV || SUBSTR(INSTR, I, 1); SET I = I - 1; END WHILE; RETURN REV; END
RETURN supplies the scalar result and ends the function. You can RETURN from more than one branch of IF. Forgetting RETURN is a CREATE-time or run-time problem — every path should return a value (or SIGNAL).
Options that matter in SQL:
Invocation is ordinary SQL: SELECT HR.REVERSE_STR(LASTNAME) FROM EMP. Function resolution uses schema, name, and argument types (overloading). QUALIFIER / PATH special registers affect which schema’s function you get, just like built-in versus user function name collisions.
An SQL table function returns a set of rows. IBM’s CREATE FUNCTION (SQL table) statement defines RETURNS TABLE (column definitions) and an SQL routine body that is a RETURN statement whose expression is a SELECT. That SELECT is copied into the invoking query. No package is generated for the table function itself.
1234567891011121314CREATE FUNCTION HR.DEPTEMPLOYEES (DEPTNO CHAR(3)) RETURNS TABLE ( EMPNO CHAR(6), LASTNAME VARCHAR(15), FIRSTNME VARCHAR(12) ) LANGUAGE SQL READS SQL DATA NO EXTERNAL ACTION DETERMINISTIC RETURN SELECT EMPNO, LASTNAME, FIRSTNME FROM DSN8C10.EMP WHERE WORKDEPT = DEPTNO;
Call it in FROM:
12SELECT T.EMPNO, T.LASTNAME FROM TABLE(HR.DEPTEMPLOYEES('A00')) AS T;
CARDINALITY integer on CREATE FUNCTION is a hint to the optimizer about expected rows — it does not enforce a limit. Because the body is a single RETURN SELECT, you do not write WHILE or handlers in an SQL table function. If you need procedural staging, return a result set from a native procedure instead, or keep the table function as a thin parameterized view and put loops in a procedure that fills a DGTT.
| Clause | What the body may do |
|---|---|
| CONTAINS SQL | SQL that does not read or write tables (SET, SIGNAL, …) |
| READS SQL DATA | SELECT / cursors allowed; no persistent-data changes |
| MODIFIES SQL DATA | INSERT UPDATE DELETE MERGE and similar (procedures; functions are more restricted) |
Procedures are the right home for MODIFIES SQL DATA plus OUT parameters. Functions in a SELECT list that quietly UPDATE will surprise every EXPLAIN and every auditor. Triggers can also contain SQL PL; they fire on data change rather than CALL or function invocation — a later tutorial section.
DROP PROCEDURE / DROP FUNCTION remove the object. ALTER FUNCTION for compiled SQL scalars follows similar versioning ideas to procedures on recent function levels — check your Db2 FL before you assume CREATE OR REPLACE. GRANT EXECUTE is what callers need; static SQL inside a compiled function or native procedure uses the package owner’s table privileges unless DYNAMICRULES say otherwise.
A native SQL procedure is a recipe card you keep in the kitchen (Db2). Someone must say CALL to cook it; they can hand you ingredients (IN) and get a plate back (OUT), or even a whole tray of cookies (result set). A scalar function is a measuring spoon: you use it inside a sentence (“give me reverse of this name”) and you get one spoonful. If the spoon is inlined, Db2 copies the measuring trick into the sentence. If it is compiled, Db2 keeps a tiny machine for that spoon. A table function is a magic lunchbox: you open it in FROM and find a list of sandwiches already made from a SELECT. You do not put a washing-machine loop inside the lunchbox — that loop belongs on a recipe card (procedure) or a compiled spoon.
1. A native SQL procedure is created with:
2. How do you run a native SQL procedure versus an SQL function?
3. Compiled versus inlined SQL scalar functions:
4. An SQL table function body is:
5. RETURN in a compiled SQL scalar function: