Control Flow Functions¶
These functions can be used to vary the outcome of queries, dependent on context, such as the values of the current row. This is often used to convert values from technical IDs to readable values, without the need to create a lookup table that needs joining. In Okera, these functions are used to replace clear-text values with obfuscated ones, like tokenized or masked values based on the original data and the permissions of the user executing the query.
Function | Description |
---|---|
CASE |
Case operator |
decode() |
Special type of Case operator |
if() |
Fixed IF ... ELSE construct |
ifnull() |
Same as if() , but more terse |
nullif() |
Returns NULL when the given arguments are equal |
The following explains the functions and statements in more detail.
-
CASE
Compares the result of an expression with one or more cases and, if one equals, returns the matching result. Syntax can be one of the following two:
CASE <reference> WHEN [<search>] THEN <result> [WHEN [<search>] THEN <result>] [ELSE <result>] END
or
CASE WHEN [<condition>] THEN <result> [WHEN [<condition>] THEN <result>] [ELSE <result>] END
All arguments are expressions, that means they are evaluated and their resulting values is used for the comparisions. For the first
CASE
form , the first match, that is where the value of<reference>
is equal to the value of a given<search>
expression, determines the associated<result>
value returned. For the second form, each<condition>
expression is evaluated and the first one to return atrue
value (that is, notfalse
,0
orNULL
) is used to return its associated<result>
value. Otherwise, it returns the value of the<result>
in theELSE
part, if given, orNULL
instead.Of note is that the first
<result>
expression result type is used to infer the types for all other results. This means that you cannot switch from, for example,10 * 10
(which is aSMALLINT
) to"foobar"
(which is aSTRING
) for separate<result>
expression in the same function call. Conversely though, other expressions can promote the infered type to a convertible one, for example, fromSMALLINT
toDOUBLE
(see last example below). Mixing types that cannot be converted, say from anINT
toSTRING
will raise an error noting the incompatible return types.Example: The two ways the
CASE
operator works> SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "more" END; one > SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END; true
-
<primitive_type> decode(<expression>, ...)
The
decode()
function works similar to theCASE
statement, but is a function insteat of a statement. Its syntax is:decode(<reference>, <search_1>, <result_1> [,<search_n>, <result_n>][, <default>])
All arguments are expressions, that means they are evaluated and their resulting values is used for the comparisions. The first match, that is where the value of
<reference>
is equal to the value of a given<search>
expression, determines the associated<result>
value returned. Otherwise, it returns the value of<default>
, if given, orNULL
instead.Of note is that the first
<result>
expression result type is used to infer the types for all other results. This means that you cannot switch from, for example,10 * 10
(which is aSMALLINT
) to"foobar"
(which is aSTRING
) for separate<result>
expression in the same function call. Conversely though, other expressions can promote the infered type to a convertible one, for example, fromSMALLINT
toDOUBLE
(see last example below). Mixing types that cannot be converted, say from anINT
toSTRING
will raise an error noting the incompatible return types.Note: This function is known from Oracle and provided for broader SQL support.
Example: Using the
decode()
function to translate values> SELECT decode(1, 1, "one", 2, "two", "something else"); one > SELECT decode(NULL, 1, "one", 2, "two", null, "not set"); not set
Example: Using expressions and implict return type inference
> SELECT decode(2.0 * 1, 1.0 * 2, 10 * 10, 2, 10 / 10, 10 + 10); -- Same as SELECT CASE 2.0 * 1 WHEN 1.0 * 2 THEN 10 * 10 WHEN 2 THEN 10 / 10 ELSE 10 + 10 END; 100 > SELECT typeof(DECODE(2, 2, 10, 2, 10 / 10, 10 + 10)); DOUBLE
-
<primitive_type> if(<expression>, ...)
Okera supports the
if()
function, with the following syntax:if(<expr1>, <expr2>, <expr3>)
. Based on the Boolean value of the first expression, the second or third expression is evaluated and its result returned. More specifically, when<expr1>
is evluating totrue
, then<expr2>
is evaluated and its result returned. Otherwise, when<expr1>
isfalse
, then`<expr3>
is evaluated and returned.Note: Okera does not support the
IF ... THEN ...
construct as known from RDBMSs. TheIF ... THEN ...
is usually used inside stored procedures, which are also not supported by Okera.Example: The
if()
function> SELECT if(NULL, 0, 1); 1 > SELECT if(0 < 1, 0, 1); 0 > SELECT if(0 > 1, 10 + 10, 20 * 20); 400
-
<primitive_type> ifnull(<expression>, <expression>)
,isnull()
, andnvl()
These functions are all equivalent and require two arguments, for instance:
ifnull(<expr1>, <expr2>)
. Similar to theif()
function, but using the first expression to make the decision, it returns the result of the first or second evaluated expression. When the first expression<expr1>
is evaluated and its result is consideredtrue
, it is returned from the function call. Otherwise,<expr2>
is evaluated and its result returned.Note: The reason for these synomyms is dialects found in commercial RDBMS systems. For example, Oracle uses
nvl()
while SQL Server is usingisnull()
. You can also express the same with thecoalesce()
function.Example: Using the
ifnull()
function> SELECT ifnull(10 * NULL, 20 * 20); 400 > SELECT ifnull(10 * 10, 20 * 20); 100
-
<primitive_type> nullif(<expression>, <expression>)
The function requires two arguments
nullif(<expr1>, <expr2>)
. It returnsNULL
if<expr1> = <expr2>
istrue
, otherwise it returns the result from evaluating<expr1>
. This is the same asCASE WHEN <expr1> = <expr2> THEN NULL ELSE <expr1> END
.Example: Using the
nullif()
function> SELECT nullif(10, 10) -- Same as: IF(10 IS DISTINCT FROM 10, 10, NULL) null > SELECT nullif(10, 11) -- Same as: IF(10 IS DISTINCT FROM 11, 10, NULL) 10