---
title: "The \"case\" statement"
url: "https://docs.yugabyte.com/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/"
---

# The "case" statement

Describes the syntax and semantics of the PL/pgSQL "case" statement. [YSQL].

## Syntax

- [![Grammar Icon](/icons/file-lines.svg)Grammar](#grammar-1)
- [![Diagram Icon](/icons/diagram.svg)Diagram](#diagram-1)

```output.ebnf
plpgsql_case_stmt ::= plpgsql_searched_case_stmt
                      | plpgsql_simple_case_stmt

plpgsql_searched_case_stmt ::= CASE  plpgsql_searched_when_leg [ ... ] 
                                [ ELSE 
                                  [ plpgsql_executable_stmt [ ... ] ] ] 
                                END CASE

plpgsql_searched_when_leg ::= WHEN guard_expression THEN 
                              [ plpgsql_executable_stmt [ ... ] ]

plpgsql_simple_case_stmt ::= CASE target_expression  
                             plpgsql_simple_when_leg [ ... ]  
                             [ ELSE 
                               [ plpgsql_executable_stmt [ ... ] ] ]  
                             END CASE

plpgsql_simple_when_leg ::= WHEN candidate_expression THEN 
                            [ plpgsql_executable_stmt [ ... ] ]
```

#### plpgsql\_case\_stmt

[plpgsql\_searched\_case\_stmt](#plpgsql-searched-case-stmt)[plpgsql\_simple\_case\_stmt](#plpgsql-simple-case-stmt)

#### plpgsql\_searched\_case\_stmt

CASE[plpgsql\_searched\_when\_leg](#plpgsql-searched-when-leg)ELSE[plpgsql\_executable\_stmt](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/syntax_resources/grammar_diagrams#plpgsql-executable-stmt)ENDCASE

#### plpgsql\_searched\_when\_leg

WHEN[guard\_expression](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/syntax_resources/grammar_diagrams#guard-expression)THEN[plpgsql\_executable\_stmt](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/syntax_resources/grammar_diagrams#plpgsql-executable-stmt)

#### plpgsql\_simple\_case\_stmt

CASE[target\_expression](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/syntax_resources/grammar_diagrams#target-expression)[plpgsql\_simple\_when\_leg](#plpgsql-simple-when-leg)ELSE[plpgsql\_executable\_stmt](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/syntax_resources/grammar_diagrams#plpgsql-executable-stmt)ENDCASE

#### plpgsql\_simple\_when\_leg

WHEN[candidate\_expression](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/syntax_resources/grammar_diagrams#candidate-expression)THEN[plpgsql\_executable\_stmt](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/case-statement/syntax_resources/grammar_diagrams#plpgsql-executable-stmt)

## Semantics

Just like the [*if* statement](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/if-statement "if statement"), the *case* statement lets you specify one or several lists of executable statements so that a maximum of one of those lists will be selected. Each list is guarded by a *boolean* *guard\_expression*—and each is tested in turn, in the order in which they are written.

The *guard\_expression* is written:

- in the *searched* *case* statement, explicitly as an *boolean* expression in each *plpgsql\_searched\_when\_leg*
- in the *simple* *case* statement, implicitly by writing the expression on the left hand side of the implied equality operator immediately after the *case* keyword that introduces the statement and by writing the expression on the right hand side of the implied equality operator immediately after the *when* keyword in each *plpgsql\_simple\_when\_leg*.

When a *guard\_expression* evaluates to *false*, the point of execution immediately moves to the next *guard\_expression*, skipping the statement list that it guards. As soon as a *guard\_expression* evaluates to *true*, the statement list that it guards is executed; and on completion of that list, control passes to the first statement after the *end case* of the *case* statement—skipping the evaluation of any remaining *guard\_expressions*. This economical testing of the *guard\_expressions* is common to many programming languages. It is a particular example of so-called short-circuit evaluation.

Critically, and in contrast to the *if* statement's semantics, the *20000* (*case not found*) error occurs if every *guard* expression (whether explicit or implicit) evaluates to *false*.

Here is the template of the simplest *case* statement:

```plpgsql
case
  when <guard_expression> then
    <guarded statement list>
end case;
```

However, this degenerate form is not useful because it has the same effect as this:

```plpgsql
assert <guard_expression>;
<guarded statement list>
```

In other words, an exception is guaranteed unless the *guard\_expression* evaluates to *true*.

The two-leg form of the *simple* *case* statement is useful when the target expression is a *boolean* variable that (if the larger context is bug-free) will always be *not null*:

```plpgsql
create procedure s.p(b in boolean)
  set search_path = pg_catalog, pg_temp
  language plpgsql
as $body$
begin
  case b
    when  true then
      <some actions>
    when false then
      <some alternative actions>
  end case;
end;
$body$;
```

Try this counter example:

```plpgsql
call s.p(null);
```

This causes the *20000* error:

```output
ERROR:  case not found
HINT:  CASE statement is missing ELSE part.
CONTEXT:  PL/pgSQL function s.p(boolean) line 3 at CASE
```

honoring the defined *case* statement semantics.

A *case* statement can always be rewritten as an *if* statement. But care must be taken to implement the *case not found* semantics when the to-be-rewritten *case* statement doesn't have a bare *else* branch.

Programmers argue about their preferences for the choice between a *case* statement and an *if* statement. See [the **tip**](/stable/api/ysql/user-defined-subprograms-and-anon-blocks/language-plpgsql-subprograms/plpgsql-syntax-and-semantics/executable-section/compound-statements/if-statement/#case-stmt-versus-if-stmt "the tip") at the send of the *if* statement page.
