Firebird Documentation Index → Firebird 2.1 Release Notes → Data Manipulation Language (DML) → Articles |
About the semantics
A select statement is used to return data to the caller (PSQL module or the client program)
Select expressions retrieve parts of data that construct columns that can be in either the final result set or in any of the intermediate sets. Select expressions are also known as subqueries.
Syntax rules
<select statement> ::= <select expression> [FOR UPDATE] [WITH LOCK] <select expression> ::= <query specification> [UNION [{ALL | DISTINCT}] <query specification>] <query specification> ::= SELECT [FIRST <value>] [SKIP <value>] <select list> FROM <table expression list> WHERE <search condition> GROUP BY <group value list> HAVING <group condition> PLAN <plan item list> ORDER BY <sort value list> ROWS <value> [TO <value>] <table expression> ::= <table name> | <joined table> | <derived table> <joined table> ::= {<cross join> | <qualified join>} <cross join> ::= <table expression> CROSS JOIN <table expression> <qualified join> ::= <table expression> [{INNER | {LEFT | RIGHT | FULL} [OUTER]}] JOIN <table expression> ON <join condition> <derived table> ::= '(' <select expression> ')'
Conclusions
FOR UPDATE mode and row locking can only be performed for a final dataset, they cannot be applied to a subquery
Unions are allowed inside any subquery
Clauses FIRST, SKIP, PLAN, ORDER BY, ROWS are allowed for any subquery
Notes
Either FIRST/SKIP or ROWS is allowed, but a syntax error is thrown if you try to mix the syntaxes
An INSERT statement accepts a select expression to define a set to be inserted into a table. Its SELECT part supports all the features defined for select statments/expressions
UPDATE and DELETE statements are always based on an implicit cursor iterating through its target table and limited with the WHERE clause. You may also specify the final parts of the select expression syntax to limit the number of affected rows or optimize the statement.
Clauses allowed at the end of UPDATE/DELETE statements are PLAN, ORDER BY and ROWS.
When aggregations, CASE evaluations and UNIONs for output columns are performed over a mix of comparable data types, the engine has to choose one data type for the result. The developer often has to prepare a variable or buffer for such results and is mystified when a request returns a data type exception. The rules followed by the engine in determining the data type for an output column under these conditions are explained here.
Let DTS be the set of data types over which we must determine the final result data type.
All of the data types in DTS shall be comparable.
In the case that
any of the data types in DTS is character string
If all data types in DTS are fixed-length character strings, then the result is also a fixed-length character string; otherwise the result is a variable-length character string.
The resulting string length, in characters, is equal to the maximum of the lengths, in characters, of the data types in DTS.
The character set and collation used are taken from the data type of the first character string in DTS.
all of the data types in DTS are exact numeric
the result data type is exact numeric with scale equal to the maximum of the scales of the data types in DTS and precision equal to the maximum precision of all data types in DTS.
any data type in DTS is approximate numeric
each data type in DTS must be numeric, otherwise an error is thrown.
any data type in DTS is a date/time data type
every data type in DTS must be a date/time type having the same date/time type, otherwise an error is thrown.
any data type in DTS is BLOB
each data type in DTS must be BLOB and all with the same sub-type.
In days gone by, before the advent of context variables like CURRENT_DATE, CURRENT_TIMESTAMP, et al., we had predefined date literals, such as 'NOW', 'TODAY', 'YESTERDAY' and so on. These predefined date literals survive in Firebird's SQL language set and are still useful.
In InterBase 5.x and lower, the following statement was “legal” and returned a DATE value ( remembering that the DATE type then was what is now TIMESTAMP):
select 'NOW' from rdb$database /* returns system date and time */
In a database of ODS 10 or higher, that statement returns the string 'NOW'. We have had to learn to cast the date literal to get the result we want:
select cast('NOW' as TIMESTAMP) from rdb$database
For a long time—probably since IB 6— there has been an undocumented
“short expression syntax” for casting not just the predefined date/time literals but
any date literals. Actually, it is defined in the standard. Most of us were just not
aware that it was available. It takes the form
<data type> <date literal>
. Taking the CAST example above, the short syntax
would be as follows:
select TIMESTAMP 'NOW' from rdb$database
This short syntax can participate in other expressions. The following example illustrates a date/time arithmetic operation on a predefined literal:
update mytable set OVERDUE = 'T' where DATE 'YESTERDAY' - DATE_DUE > 10
Firebird Documentation Index → Firebird 2.1 Release Notes → Data Manipulation Language (DML) → Articles |