> ## Documentation Index
> Fetch the complete documentation index at: https://www.cockroachlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CREATE PROCEDURE

export const InlineImage = ({src, alt = "", height = "1.6em"}) => {
  return <img noZoom src={src} alt={alt} style={{
    display: "inline",
    verticalAlign: "start",
    height: height,
    margin: "0"
  }} />;
};

export const InternalLink = ({version, path = "", children, ...props}) => {
  let detectedVersion = version || "stable";
  if (typeof window !== 'undefined' && !version) {
    const match = window.location.pathname.match(/\/docs\/([^/]+)/);
    if (match) {
      detectedVersion = match[1];
    }
  }
  const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
  return <a href={`/docs/${detectedVersion}/${normalizedPath}`} {...props}>
      {children}
    </a>;
};

<InlineImage alt="Megaphone" src="/images/common/icon-megaphone.png" /> New in v23.2: The `CREATE PROCEDURE` <InternalLink path="sql-statements">statement</InternalLink> defines a <InternalLink path="stored-procedures">stored procedure</InternalLink>.

## Required privileges

* To define a procedure, a user must have <InternalLink path="security-reference/authorization#supported-privileges">`CREATE` privilege</InternalLink> on the schema of the procedure.
* To define a procedure with a <InternalLink path="create-type">user-defined type</InternalLink>, a user must have <InternalLink path="security-reference/authorization#supported-privileges">`USAGE` privilege</InternalLink> on the user-defined type.
* To resolve a procedure, a user must have at least the <InternalLink path="security-reference/authorization#supported-privileges">`USAGE` privilege</InternalLink> on the schema of the procedure.
* To <InternalLink path="call">call a procedure</InternalLink>, a user must have <InternalLink path="security-reference/authorization#supported-privileges">`EXECUTE` privilege</InternalLink> on the procedure.
* At procedure definition and execution time, a user must have privileges on all the objects referenced in the procedure body. Privileges on referenced objects can be revoked and later procedure calls can fail due to lack of permission.

If you grant `EXECUTE` privilege as a default privilege at the database level, newly created procedures inherit that privilege from the database.

## Synopsis

<img src="https://mintcdn.com/cockroachlabs/hRoSoqt0mqHbZVjm/images/sql-diagrams/v23.2/create_proc.svg?fit=max&auto=format&n=hRoSoqt0mqHbZVjm&q=85&s=73f2eb8e4ca3e2cabe5d44a8bb4a2803" alt="create_proc syntax diagram" style={{maxWidth: "100%", overflowX: "auto"}} width="671" height="315" data-path="images/sql-diagrams/v23.2/create_proc.svg" />

## Parameters

| Parameter               | Description                                                                                                                             |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `routine\_create\_name` | The name of the procedure.                                                                                                              |
| `routine\_param`        | A comma-separated list of procedure parameters.                                                                                         |
| `routine\_body\_str`    | The body of the procedure. For allowed contents, see <InternalLink path="stored-procedures#structure">Stored Procedures</InternalLink>. |

## Examples

The following are examples of basic stored procedures. For a more detailed example of a stored procedure, see <InternalLink path="stored-procedures">Create a stored procedure using PL/pgSQL</InternalLink>.

### Create a stored procedure that uses a composite-type variable

Create a <InternalLink path="create-type#create-a-composite-data-type">composite variable</InternalLink>:

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE TYPE comp AS (x INT, y STRING);
```

Create the procedure, declaring the `comp` variable you created:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE OR REPLACE PROCEDURE proc() LANGUAGE PLpgSQL AS $$
  DECLARE
    v comp := ROW(1, 'foo');
  BEGIN
    RAISE NOTICE '%', v;
  END
  $$;
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CALL proc();
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
NOTICE: (1,foo)
CALL
```

### Create a stored procedure that uses conditional logic

The following example uses <InternalLink path="plpgsql#write-conditional-statements">PL/pgSQL conditional statements</InternalLink>:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE OR REPLACE PROCEDURE proc(a INT, b INT) AS
  $$
  DECLARE
    result INT;
  BEGIN
    IF a > b THEN
      RAISE NOTICE 'Condition met: a is greater than b';
    ELSE
      RAISE NOTICE 'Condition not met: a is not greater than b';
    END IF;
  END;
  $$ LANGUAGE PLpgSQL;
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CALL proc(1, 2);
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
NOTICE: Condition not met: a is not greater than b
CALL
```

### Create a stored procedure that uses a `WHILE` loop

The following example uses <InternalLink path="plpgsql#write-loops">PL/pgSQL loop statements</InternalLink>:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE OR REPLACE PROCEDURE arr_var() AS
  $$
  DECLARE
    x INT[] := ARRAY[1, 2, 3, 4, 5];
    n INT;
    i INT := 1;
  BEGIN
    n := array_length(x, 1);
    WHILE i <= n LOOP
      RAISE NOTICE '%: %', i, x[i];
      i := i + 1;
    END LOOP;
  END
  $$ LANGUAGE PLpgSQL;
```

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CALL arr_var();
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
NOTICE: 1: 1
NOTICE: 2: 2
NOTICE: 3: 3
NOTICE: 4: 4
NOTICE: 5: 5
```

## See also

* <InternalLink path="stored-procedures">Stored Procedures</InternalLink>
* <InternalLink path="plpgsql">PL/pgSQL</InternalLink>
* <InternalLink path="call">`CALL`</InternalLink>
* <InternalLink path="alter-procedure">`ALTER PROCEDURE`</InternalLink>
* <InternalLink path="drop-procedure">`DROP PROCEDURE`</InternalLink>
