CALL statement. This allows complex logic to be executed repeatedly within the database, which can improve performance and mitigate security risks.
Both stored procedures and user-defined functions are types of routines. However, they differ in the following ways:
- Functions return a value, and procedures do not return a value.
- Procedures must be invoked using a
CALLstatement. Functions can be invoked in nearly any context, such asSELECT,FROM, andWHEREclauses,DEFAULTexpressions, and computed column expressions. - Functions have volatility 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 SQL data type, user-defined type, or the PL/pgSQL
REFCURSORtype, when declaring PL/pgSQL cursor variables. - CockroachDB supports the
IN(default),OUT, andINOUTmodes for parameters. For an example, see Create a procedure that usesOUTandINOUTparameters. LANGUAGEspecifies the language of the function body. CockroachDB supports the languagesSQLandPLpgSQL.- 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 block structure if written in PL/pgSQL.
- Can be enclosed in single or dollar (
CREATE PROCEDURE.
Examples
Setup
To follow along, runcockroach demo to start a temporary, in-memory cluster with the movr sample dataset preloaded:
CREATE PROCEDURE.
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 WHILE 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:CREATE PROCEDURE defines a stored procedure called delete_earliest_histories with an INT and a REFCURSOR parameter.
LANGUAGE specifies PL/pgSQL as the language for the stored procedure.
DECLARE specifies the PL/pgSQL variable definitions that are used in the procedure body.
BEGIN and END group the PL/pgSQL statements in the procedure body.
IF ... THEN statement raises an exception if 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.
WHILE loop deletes rows iteratively from 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 Assign a result to a variable.
Finally, the RAISE NOTICE statement reports these values for each deleted row.
OPEN statement opens a cursor 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 thedelete_earliest_histories example procedure to delete_histories:
Known limitations
Stored procedures have the following limitations:-
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 anyENUMtype. 123048

