Firebird 2.5 Language ReferenceFirebird 2.5 Language ReferenceCommon Language Elements → Expressions
Firebird Firebird Prev: Common Language ElementsFirebird 2.5 Language ReferenceUp: Common Language ElementsNext: Predicates

Expressions

SQL Operators
Conditional Expressions
NULL in Expressions
Subqueries

SQL expressions provide formal methods for evaluating, transforming and comparing values. SQL expressions may include table columns, variables, constants, literals, various statements and predicates and also other expressions. The complete list of possible tokens in expressions follows.

Table 4.1. Description of Expression Elements

Element Description
Column name Identifier of a column from a specified table used in evaluations or as a search condition. A column of the array type cannot be an element in an expression except when used with the IS [NOT] NULL predicate.
Array element An expression may contain a reference to an array element
Arithmetic operators The +, -, *, / characters used to calculate values
Concatenation operator The || (“double-pipe”) operator used to concatenate strings
Logical operators The reserved words NOT, AND and OR, used to combine simple search conditions in order to create complex assertions
Comparison operators The symbols =, <>, !=, ~=, ^=, <, <=, >, >=, !<, ~<, ^<, !>, ~> and ^>
Comparison predicates LIKE, STARTING WITH, CONTAINING, SIMILAR TO, BETWEEN, IS [NOT] NULL and IS [NOT] DISTINCT FROM
Existential predicates Predicates used to check the existence of values in a set. The IN predicate can be used both with sets of comma-separated constants and with subqueries that return a single column. The EXISTS, SINGULAR, ALL, ANY and SOME predicates can be used only with subqueries
Constant A number; or a string literal enclosed in apostrophes
Date/time literal An expression, similar to a string literal enclosed in apostrophes, that can be interpreted as a date, time or timestamp value. Date literals can be predefined literals ('TODAY', 'NOW', etc.) or strings of characters and numerals, such as '25.12.2016 15:30:35', that can be resolved as date and/or time strings
Context variable An internally-defined context variable
Local variable Declared local variable, input or output parameter of a PSQL module (stored procedure, trigger, unnamed PSQL block in DSQL)
Positional parameter A member of in an ordered group of one or more unnamed parameters passed to a stored procedure or prepared query
Subquery A SELECT statement enclosed in parentheses that returns a single (scalar) value or, when used in existential predicates, a set of values
Function identifier The identifier of an internal or external function in a function expression
Type cast An expression explicitly converting data of one data type to another using the CAST function ( CAST (<value> AS <datatype>) ). For date/time literals only, the shorthand syntax <datatype> <value> is also supported (DATE '25.12.2016')
Conditional expression Expressions using CASE and related internal functions
Parentheses Bracket pairs (…) used to group expressions. Operations inside the parentheses are performed before operations outside them. When embedded parentheses are used, the most deeply embedded expressions are evaluated first and then the evaluations move outward through the levels of embedding
COLLATE clause Clause applied to CHAR and VARCHAR types to specify the collation sequence to use in string comparisons
NEXT VALUE FOR sequence Expression for obtaining the next value of a specified generator (sequence). The internal GEN_ID() function does the same


SQL Operators

SQL operators comprise operators for comparing, calculating, evaluating and concatenating values.

Operator Precedence

SQL Operators are divided into four types. Each operator type has a precedence, a ranking that determines the order in which operators and the values obtained with their help are evaluated in an expression.The higher the precedence of the operator type is, the earlier it will be evaluated. Each operator has its own precedence within its type, that determines the order in which they are evaluated in an expression.

Operators with the same precedence are evaluated from left to right. To force a different evaluation order, operations can be grouped by means of parentheses.

Table 4.2. Operator Type Precedence

Operator Type Precedence Explanation
Concatenation 1 Strings are concatenated before any other operations take place
Arithmetic 2 Arithmetic operations are performed after strings are concatenated, but before comparison and logical operations
Comparison 3 Comparison operations take place after string concatenation and arithmetic operations, but before logical operations
Logical 4 Logical operators are executed after all other types of operators


Concatenation Operator

The concatenation operator, two pipe characters known as “double pipe”— || — concatenates (connects together) two character strings to form a single string. Character strings can be constants or values obtained from columns or other expressions.

Example: 

       SELECT LAST_NAME || ', ' || FIRST_NAME AS FULL_NAME
       FROM EMPLOYEE
            
Arithmetic Operators

Table 4.3. Arithmetic Operator Precedence

Operator Purpose Precedence
* Multiplication 1
/ Division 2
+ Addition 3
- Subtraction 4


Example: 

       UPDATE T
         SET A = 4 + 1/(B-C)*D
            
Comparison Operators

Table 4.4. Comparison Operator Precedence

Operator Purpose Precedence
= Is equal to, is identical to 1
<>, !=, ~=, ^= Is not equal to 2
> Is greater than 3
< Is less than 4
>= Is greater than or equal to 5
<= Is less than or equal to 6
!>, ~>, ^> Is not greater than 7
!<, ~<, ^< Is not less than 8


This group also includes comparison predicates BETWEEN, LIKE, CONTAINING, SIMILAR TO and others.

Example: 

       IF (SALARY > 1400) THEN
       …
            

See also: Other Comparison Predicates.

Logical Operators

Table 4.5. Logical Operator Precedence

Operator Purpose Precedence
NOT Negation of a search condition 1
AND Combines two or more predicates, each of which must be true for the entire predicate to be true 2
OR Combines two or more predicates, of which at least one predicate must be true for the entire predicate to be true 3


Example: 

       IF (A < B OR (A > C AND A > D) AND NOT (C = D)) THEN …
            

NEXT VALUE FOR

Available: DSQL, PSQL

NEXT VALUE FOR returns the next value of a sequence. SEQUENCE is an SQL-compliant term for a generator in Firebird and its ancestor, InterBase. The NEXT VALUE FOR operator is equivalent to the legacy GEN_ID (..., 1) function and is the recommended syntax for retrieving the next sequence value.

Syntax for NEXT VALUE FOR: 

       NEXT VALUE FOR sequence-name
          

Example: 

       NEW.CUST_ID = NEXT VALUE FOR CUSTSEQ;
          
[Note] Note

Unlike GEN_ID (..., 1), the NEXT VALUE FOR variant does not take any parameters and thus, provides no way to retrieve the current value of a sequence, nor to step the next value by more than 1. GEN_ID (..., <step value>) is still needed for these tasks. A <step value> of 0 returns the current sequence value.

See also:  SEQUENCE (GENERATOR), GEN_ID()

Conditional Expressions

A conditional expression is one that returns different values according to how a certain condition is met. It is composed by applying a conditional function construct, of which Firebird supports several. This section describes only one conditional expression construct: CASE. All other conditional expressions apply internal functions derived from CASE and are described in Conditional Functions.

CASE

Available:  DSQL, PSQL

The CASE construct returns a single value from a number of possible ones. Two syntactic variants are supported:

  • The simple CASE, comparable to a case construct in Pascal or a switch in C
  • The searched CASE, which works like a series of  “if ... else if ... else if”  clauses.

Simple CASE

Syntax: 

       …
       CASE <test-expr>
         WHEN <expr> THEN <result>
         [WHEN <expr> THEN <result> ...]
         [ELSE <defaultresult>]
       END
       …
            

When this variant is used, <test-expr> is compared to <expr> 1, <exp> 2 etc., until a match is found and the corresponding result is returned. If no match is found, <defaultresult> from the optional ELSE clause is returned. If there are no matches and no ELSE clause, NULL is returned.

The matching works identically to the "=" operator. That is, if <test-expr> is NULL, it does not match any <expr>, not even an expression that resolves to NULL.

The returned result does do not have to be a literal value: it might be a field or variable name, compound expression or NULL literal.

A short form of the simple CASE construct is used in the DECODE function.

Example: 

       SELECT
         NAME,
         AGE,
         CASE UPPER(SEX)
           WHEN 'M' THEN 'Male'
           WHEN 'F' THEN 'Female'
           ELSE 'Unknown'
         END GENDER,
	RELIGION
      FROM PEOPLE
              

Searched CASE

Syntax: 

       CASE
         WHEN <bool_expr> THEN <result>
         [WHEN <bool_expr> THEN <result> …]
         [ELSE <defaultresult>]
         END
            

The <bool_expr> expression is one that gives a ternary logical result: TRUE, FALSE or NULL. The first expression to return TRUE determines the result. If no expressions return TRUE, <defaultresult> from the optional ELSE clause is returned as the result. If no expressions return TRUE and there is no ELSE clause, the result will be NULL.

As with the simple CASE construct, the result must not be a literal value: it might be a field or variable name, a compound expression, or be NULL.

Example: 

       CANVOTE = CASE
         WHEN AGE >= 18 THEN 'Yes'
         WHEN AGE < 18 THEN 'No'
         ELSE 'Unsure'
         END
            

NULL in Expressions

NULL is not a value in SQL, but a state indicating that the value of the element either unknown or it does not exist. It is not a zero, nor a void, nor an “empty string”, and it does not act like any value.

When you use NULL in numeric, string or date/time expressions, the result will always be NULL. When you use NULL in logical (Boolean) expressions, the result will depend on the type of the operation and on other participating values. When you compare a value to NULL, the result will be unknown.

[Important] Important to Note

NULL means NULL but, in Firebird, the logical result unknown is also represented by NULL.

Expressions Returning NULL

Expressions in this list will always return NULL:

       1 + 2 + 3 + NULL
       'Home ' || 'sweet ' || NULL
       MyField = NULL
       MyField <> NULL
       NULL = NULL
       not (NULL)
          

If it seems difficult to understand why, remember that NULL is a state that stands for “unknown”.

NULL in Logical Expressions

It has already been shown that not (NULL) results in NULL. The interaction is a bit more complicated for the logical AND and logical OR operators:

       NULL or false = NULL
       NULL or true = true
       NULL or NULL = NULL
       NULL and false = false
       NULL and true = NULL
       NULL and NULL = NULL
          

Up to and including Firebird 2.5.x, there is no implementation for a logical (Boolean) data type—that is coming in Firebird 3. However, there are logical expressions (predicates) that can return true, false or unknown.

Examples: 

       (1 = NULL) or (1 <> 1) -- returns NULL
       (1 = NULL) or (1 = 1) -- returns TRUE
       (1 = NULL) or (1 = NULL) -- returns NULL
       (1 = NULL) and (1 <> 1) -- returns FALSE
       (1 = NULL) and (1 = 1) -- returns NULL
       (1 = NULL) and (1 = NULL) -- returns NULL
            

Subqueries

A subquery is a special form of expression that is actually a query embedded within another query. Subqueries are written in the same way as regular SELECT queries, but they must be enclosed in parentheses. Subquery expressions can be used in the following ways:

  • To specify an output column in the SELECT list
  • To obtain values or conditions for search predicates (the WHERE, HAVING clauses).
  • To produce a set that the enclosing query can select from, as though were a regular table or view. Subqueries like this appear in the FROM clause (derived tables) or in a Common Table Expression (CTE)

Correlated Subqueries

A subquery can be correlated. A query is correlated when the subquery and the main query are interdependent. To process each record in the subquery, it is necessary to fetch a record in the main query; i.e., the subquery fully depends on the main query.

Sample Correlated Subquery: 

       SELECT *
       FROM Customers C
       WHERE EXISTS
             (SELECT *
              FROM Orders O
              WHERE C.cnum = O.cnum
                AND O.adate = DATE '10.03.1990');
          

When subqueries are used to get the values of the output column in the SELECT list, a subquery must return a scalar result.

Scalar Results

Subqueries used in search predicates, other than existential and quantified predicates, must return a scalar result; that is, not more than one column from not more than one matching row or aggregation. If the result would return more, a run-time error will occur (“Multiple rows in a singleton select...”).

[Note] Note

Although it is reporting a genuine error, the message can be slightly misleading. A “singleton SELECT” is a query that must not be capable of returning more than one row. However, “singleton” and “scalar” are not synonymous: not all singleton SELECTS are required to be scalar; and single-column selects can return multiple rows for existential and quantified predicates.

Subquery Examples: 

  1. A subquery as the output column in a SELECT list:
           SELECT
               e.first_name,
               e.last_name,
               (SELECT
                    sh.new_salary
                FROM
                    salary_history sh
                WHERE
                    sh.emp_no = e.emp_no
                ORDER BY sh.change_date DESC ROWS 1) AS last_salary
           FROM
                employee e
                  
  2. A subquery in the WHERE clause for obtaining the employee's maximum salary and filtering by it:
           SELECT
               e.first_name,
               e.last_name,
               e.salary
           FROM
               employee e
           WHERE
               e.salary = (
                           SELECT MAX(ie.salary)
                           FROM employee ie
                           )
                  
Prev: Common Language ElementsFirebird 2.5 Language ReferenceUp: Common Language ElementsNext: Predicates
Firebird 2.5 Language ReferenceFirebird 2.5 Language ReferenceCommon Language Elements → Expressions