- Functions return a value, and procedures do not return a value.
- Procedures must be invoked using a statement. Functions can be invoked in nearly any context, such as
SELECT,FROM, andWHEREclauses, expressions, and expressions. - Functions have settings, and procedures do not.
Structure
A stored procedure consists of a name, optional parameters, language, and procedure body.- Each parameter can be a supported , , or the PL/pgSQL
REFCURSORtype, when . - CockroachDB supports the
IN(default),OUT, andINOUTmodes for parameters. For an example, see . LANGUAGEspecifies the language of the function body. CockroachDB supports the languages and .- The procedure body:
- Can be enclosed in single or dollar (
$$) quotes. Dollar quotes are easier to use than single quotes, which require that you escape other single quotes that are within the procedure body. - Must conform to a if written in PL/pgSQL.
- Can be enclosed in single or dollar (
Statement statistics
SQL statements executed within stored procedures are tracked in the SQL statistics subsystem and will appear in the page and the page in the DB Console. This allows you to monitor the performance and execution statistics of individual statements within your procedures. When the stored procedure is invoked as part of a transaction, the statements executed within the procedure will also appear in the in the Statement Fingerprints table. cannot be collected for statements executed inside stored procedures. You can request statement diagnostics for the top-level invocation of the procedure, and the resulting trace includes spans for each statement executed. However, there is no way to target statements executed inside the procedure with a statement diagnostics request. For details, refer to Known limitations.
Examples
Setup
To follow along, run to start a temporary, in-memory cluster with the sample dataset preloaded:Create a stored procedure using PL/pgSQL
The following stored procedure removes a specified number of earliest rides invehicle_location_histories.
It uses the PL/pgSQL syntax to iterate through the rows, [RAISE] to return notice and error messages, and REFCURSOR to define a cursor that fetches the next rows to be affected by the procedure.
rides_left cursor name:
vehicle_location_histories:
Example details
The example works as follows: defines a stored procedure calleddelete_earliest_histories with an INT and a REFCURSOR parameter.
LANGUAGE specifies as the language for the stored procedure.
DECLARE specifies the that are used in the procedure body.
BEGIN and END in the procedure body.
vehicle_location_histories has fewer rows than the number specified with num_deletions. If the exception is raised within an open transaction, the transaction will abort.
vehicle_location_histories, stopping when the number of loops reaches the num_deletions value.
The DELETE ... RETURNING ... INTO statement assigns column values from each deleted row into separate variables. For more information about assigning variables, see .
Finally, the statement reports these values for each deleted row.
OPEN statement for all remaining rows in vehicle_location_histories, sorted by timestamp. After calling the procedure in an open transaction, the cursor can be used to fetch rows from the table.
Alter a stored procedure
The following statement renames the todelete_histories:
Known limitations
Stored procedures have the following limitations:- Pausable portals are not supported with
CALLstatements for stored procedures. COMMITandROLLBACKstatements are not supported within nested procedures.- Routines cannot be invoked with named arguments, e.g.,
SELECT foo(a => 1, b => 2);orSELECT foo(b := 1, a := 2);. - Routines cannot be created if they reference temporary tables.
- Routines cannot be created with unnamed
INOUTparameters. For example,CREATE PROCEDURE p(INOUT INT) AS $$ BEGIN NULL; END; $$ LANGUAGE PLpgSQL;. - Routines cannot be created if they return fewer columns than declared. For example,
CREATE FUNCTION f(OUT sum INT, INOUT a INT, INOUT b INT) LANGUAGE SQL AS $$ SELECT (a + b, b); $$;. - Routines cannot be created with an
OUTparameter of typeRECORD. - DDL statements (e.g.,
CREATE TABLE,CREATE INDEX) are not allowed within UDFs or stored procedures. - Polymorphic types cannot be cast to other types (e.g.,
TEXT) within routine parameters. - Routine parameters and return types cannot be declared using the
ANYENUMpolymorphic type, which is able to match any type. - cannot be collected for statements executed inside UDFs or stored procedures. You can request statement diagnostics for the top-level invocation of the function or procedure, and the resulting trace includes spans for each statement executed. However, there is no way to target statements executed inside the function or procedure with a statement diagnostics request.
- Statements within routines do not currently respect hint injections. The workaround is to modify the inline hints directly in the body by replacing the routine.

