FirebirdSQL logo

Арифметические операторы

Table 1. Приоритет арифметических операторов
Оператор Назначение Приоритет

+signed_number

Унарный плюс

1

-signed_number

Унарный минус

1

*

Умножение

2

/

Деление

2

+

Сложение

3

-

Вычитание

3

Example 1. Арифметические операторы
UPDATE T
SET A = 4 + 1/(B-C)*D

Операторы сравнения

Table 1. Операторы сравнения
Оператор Назначение Приоритет

IS

Проверяет, что выражение в левой части является псевдозначением NULL или соответствует логическому значению вправой части.

1

=

Равно, идентично

2

<>, !=, ~=, ^=

Не равно

2

>

Больше

2

<

Меньше

2

>=

Больше или равно

2

<=

Меньше или равно

2

!>, ~>, ^>

Не больше

2

!<, ~<, ^<

Не меньше

2

В эту же группу входят предикаты сравнения IS DISTINCT FROM, BETWEEN, IN, LIKE, CONTAINING, SIMILAR TO и другие.

Example 1. Использование оператора сравнения
IF (SALARY > 1400) THEN
...

docnext count = 44

Логические операторы

Table 1. Приоритет логических операторов
Оператор Назначение Приоритет

NOT

Отрицание условия поиска.

1

AND

Объединяет два предиката и более, каждый из которыхдолжен быть истинным, чтобы истинным был и весьпредикат.

2

OR

Объединяет два предиката и более, из которых должен бытьистинным хотя бы один предикат, чтобы истинным был и весьпредикат.

3

Example 1. Использование логических операторов
IF (A > B OR (A > C AND A > D) AND NOT (C = D)) THEN
...

AT

Доступно в

DSQL, PSQL.

Синтаксис
<expr> AT {TIME ZONE <time zone string> | LOCAL}

<time zone string> ::=
    '<time zone>'

<time zone> ::=
    <time zone region> |
    [+/-] <hour displacement> [: <minute displacement>]

Преобразует время или временную метку в указанный часовой пояс.Если используется ключевое слово LOCAL, то преобразование происходит в часовой пояс сессии.

Example 1. Использование функции AT
select time '12:00 GMT' at time zone '-03'
  from rdb$database;

select current_timestamp at time zone 'America/Sao_Paulo'
  from rdb$database;

select timestamp '2018-01-01 12:00 GMT' at local
  from rdb$database;

NEXT VALUE FOR

Доступно вDSQL, PSQL.

Синтаксис
NEXT VALUE FOR sequence-name

Возвращает следующее значение в последовательности (SEQUENCE). SEQUENCE является SQL совместимым термином генератора в InterBase и Firebird.Оператор NEXT VALUE FOR полностью эквивалентен функции GEN_ID (sequence-name, 1) и является рекомендуемым синтаксисом.

Note

NEXT VALUE FOR не поддерживает значение приращения, отличное от того, что было указано при создании последовательности в предложении INCREMENT [BY]. Если требуется другое значение шага, то используйте старую функцию GEN_ID.

Example 1. Использование NEXT VALUE FOR
NEW.CUST_ID = NEXT VALUE FOR CUSTSEQ;
См. также:

SEQUENCE (GENERATOR), GEN_ID.

Условные выражения

Условное выражение — это выражение, которое возвращает различные значения в зависимости от истинности некоторого условия или условий.В данном разделе описано лишь одно условное выражение CASE.Остальные условные выражения являются производными встроенными функциями и описаны в разделе Условные функции.

CASE

Доступно в

DSQL, ESQL.

Оператор CASE возвращает только одно значение из нескольких возможных.Есть два синтаксических варианта:

  • Простой CASE, сравнимый с Pascal case или C switch;

  • Поисковый CASE, который работает как серия операторов “if …​ else if …​ else if”.

Простой CASE
Синтаксис
CASE <test-expr>
  WHEN <expr> THEN <result>
  [WHEN <expr> THEN <result> ...]
  [ELSE <defaultresult>]
END

При использовании этого варианта test-expr сравнивается с первым expr,затем вторым expr и так далее,до тех пор, пока не будет найдено совпадение, и тогда возвращается соответствующий результат.Если совпадений не найдено, то возвращается defaultresult из ветви ELSE.Если нет совпадений, и ветвь ELSE отсутствует, то возвращается значение NULL.

Совпадение эквивалентно оператору “=”, то естьесли test-expr имеет значение NULL, то он не соответствует ни одному из expr, даже тем, которые имеют значение NULL.

Результаты необязательно должны быть литеральными значениями, они также могут быть именами полей, переменными, сложными выражениями или NULL.

Example 1. Использование простого CASE
SELECT
  NAME,
  AGE,
  CASE UPPER(SEX)
    WHEN 'M' THEN 'Male'
    WHEN 'F' THEN 'Female'
    ELSE 'Unknown'
  END AS SEXNAME,
  RELIGION
FROM PEOPLE

Сокращённый вид простого оператора CASE используется в функции DECODE.

Поисковый CASE
Синтаксис
CASE
  WHEN <bool_expr> THEN <result>
  [WHEN <bool_expr> THEN <result> …]
  [ELSE <defaultresult>]
END

Здесь <bool_expr> выражение, которое даёт тройной логический результат: TRUE, FALSE или NULL.Первое выражение, возвращающее TRUE, определяет результат.Если нет выражений, возвращающих TRUE, то в качестве результата берётся defaultresult из ветви ELSE.Если нет выражений, возвращающих TRUE, и ветвь ELSE отсутствует, результатом будет NULL.

Как и в простом операторе CASE, результаты не обязаны быть литеральными значениями: они могут быть полями или именами переменных, сложными выражениями, или NULL.

Example 1. Использование поискового CASE
CANVOTE = CASE
  WHEN AGE >= 18 THEN 'Yes'
  WHEN AGE < 18 THEN 'No'
  ELSE 'Unsure'
END;

NULL в выражениях

NULL не является значением — это состояние, указывающее, что значение элемента неизвестно или не существует.Это не ноль, не пустота, не “пустая строка”, и оно не ведёт себя как какое-то из этих значений.

При использовании NULL в числовых, строковых выражениях или в выражениях, содержащих дату/время, в результате вы всегда получите NULL.При использовании NULL в логических (булевых) выражениях результат будет зависеть от типа операции и других вовлечённых значений.При сравнении значения с NULL результат будет неопределённым (UNKNOWN).

Important

Неопределённый логический результат UNKNOWN тоже представлен псевдо-значением NULL.

Выражения возвращающие NULL

Выражения в этом списке всегда возвратят NULL:

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

Если вам трудно понять, почему, вспомните, что NULL — значит “неизвестно”.

NULL в логических выражениях

Мы уже рассмотрели, что not (NULL) даёт в результате NULL.Для операторов AND и OR взаимодействие несколько сложнее:

NULL or false → NULL
NULL or true → true
NULL or NULL → NULL
NULL and false → false
NULL and true → NULL
NULL and NULL → NULL
Example 1. NULL в логических выражениях
(1 = NULL) or (1 <> 1)    -- returns NULL
(1 = NULL) or FALSE       -- returns NULL
(1 = NULL) or (1 = 1)     -- returns TRUE
(1 = NULL) or TRUE        -- returns TRUE
(1 = NULL) or (1 = NULL)  -- returns NULL
(1 = NULL) or UNKNOWN     -- returns NULL
(1 = NULL) and (1 <> 1)   -- returns FALSE
(1 = NULL) and FALSE      -- returns FALSE
(1 = NULL) and (1 = 1)    -- returns NULL
(1 = NULL) and TRUE       -- returns NULL
(1 = NULL) and (1 = NULL) -- returns NULL
(1 = NULL) and UNKNOWN    -- returns NULL

Подзапросы

Подзапрос — это специальный вид выражения, которое фактически является запросом, встроенным в другой запрос.Подзапросы пишутся как обычные SELECT запросы, но должны быть заключены в круглые скобки.Выражения подзапроса используется следующими способами:

  • Для задания выходного столбца в списке выбора SELECT;

  • Для получения значений или условий для предикатов поиска (предложения WHERE, HAVING);

  • Для создания набора данных, из которого включающий запрос может выбирать, как будто это обычная таблица или представление.Подобные подзапросы появляются в предложении FROM (производные таблицы) или в общем табличном выражении (CTE).

Коррелированные подзапросы

Подзапрос может быть коррелированным (соотнесённым). Запрос называется коррелированным, когда подзапрос и основной запрос взаимозависимы.Это означает, что для обработки каждой записи подзапроса, должна быть получена также запись из основного запроса, т.е.подзапрос всецело зависит от основного запроса.

Example 1. Коррелированный подзапрос
SELECT *
FROM Customers C
WHERE EXISTS
      (SELECT *
       FROM Orders O
       WHERE C.cnum = O.cnum
         AND O.adate = DATE '10.03.1990');

При использовании подзапросов для получения значений выходного столбца в списке выбора SELECT, подзапрос должен возвращать скалярный результат.

Подзапросы возвращающие скалярный результат

Подзапросы, используемые в предикатах поиска, кроме предикатов существования и количественных предикатов, должны возвращать скалярный результат, то есть не более чем один столбец из одной отобранной строки или одно агрегированное значение, в противном случае, произойдёт ошибка времени выполнения (“Multiple rows in a singleton select…​”).

Note

Несмотря на то, что Firebird сообщает о подлинной ошибке, сообщение может немного вводить в заблуждение.“singleton SELECT” — это запрос, который не должен возвращать более одной строки.Однако “singleton” и “scalar” не являются синонимами: не все одноэлементные SELECTS должны быть скалярными; а выборка по одному столбцу может возвращать несколько строк для предикатов существования и количественных предикатов.

Example 1. Подзапрос в качестве выходного столбца в списке выбора
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
Example 2. Подзапрос в предложении WHERE для получения значения максимальной зарплаты сотрудника и фильтрации по нему
SELECT
    e.first_name,
    e.last_name,
    e.salary
FROM
    employee e
WHERE
    e.salary = (SELECT
                    MAX(ie.salary)
                FROM
                    employee ie)

Предикаты

Предикат — это простое выражение, утверждающее некоторый факт, назовем его P.Если P разрешается как TRUE, он успешен.Если он принимает значение FALSE или NULL (UNKNOWN), он терпит неудачу.Однако здесь кроется ловушка: предположим, что предикат P возвращает FALSE.В этом случае NOT (P) вернет TRUE.С другой стороны, если P возвращает NULL (неизвестно), то NOT (P) также возвращает NULL.

В SQL предикаты проверяют в ограничении CHECK, предложении WHERE, выражении CASE, условии соединения во фразе ON для предложений JOIN, а также в предложении HAVING.В PSQL операторы управления потоком выполнения проверяют предикаты в предложениях IF, WHILE и WHEN. Поскольку начиная с Firebird 3.0 введена поддержка логического типа, то предикат может встречаться в любом правильном выражении.

Утверждения

Проверяемые условия не всегда являются простыми предикатами.Они могут быть группой предикатов, каждый из которых при вычислении делает вклад в вычислении общей истинности.Такие сложные условия называются утверждениями.Утверждения могут состоять из одного или нескольких предикатов, связанных логическими операторами AND, OR и NOT. Для группировки предикатов и управления порядком вычислений можно использовать скобки.

Каждый из предикатов может содержать вложенные предикаты.Результат вычисления истинности утверждения получается в результате вычисления всех предикатов по направлению от внутренних к внешним.Каждый “уровень” вычисляется в порядке приоритета до тех пор, пока не будет получено значение истинности окончательного утверждения.

Предикаты сравнения

Предикат сравнения представляет собой два выражения, соединяемых оператором сравнения.Имеется шесть традиционных операторов сравнения:

=, >, <, >=, <=, <>

(Полный список операторов сравнения см. Операторы сравнения).

Если в одной из частей (левой или правой) предиката сравнения встречается NULL, то значение предиката будет неопределённым (UNKNOWN).

Example 1. Предикаты сравнения

Получить информацию о компьютерах, имеющих частоту процессора не менее 500 МГц и цену ниже $800

SELECT *
FROM Pc
WHERE speed >= 500 AND price < 800;

Получить информацию обо всех принтерах, которые являются матричными и стоят меньше $300

SELECT *
FROM Printer
WHERE type = 'matrix' AND price < 300;

Следующий запрос не вернёт ни одной записи, поскольку сравнение происходит с псевдо-значением NULL, даже если существуют принтеры с неуказанным типом.

SELECT *
FROM Printer
WHERE type = NULL AND price < 300;
Note
Замечание о сравнении строк

При сравнении на равенство полей типов CHAR и VARCHAR завершающий пробелы игнорируются во всех случаях.

Другие предикаты сравнения

Другие предикаты сравнения состоят из ключевых слов.

BETWEEN

Доступно в

DSQL, PSQL, ESQL.

Синтаксис
<value> [NOT] BETWEEN <value_1> AND <value_2>

Предикат BETWEEN проверяет, попадает (или не попадает при использовании NOT) ли значение во включающий диапазон значений.

Операнды для предиката BETWEEN — это два аргумента совместимых типов.В отличие от некоторых других СУБД в Firebird предикат BETWEEN не является симметричным.Меньшее значение должно быть первым аргументом, иначе предикат BETWEEN всегда будет ложным.Поиск является включающим.Таким образом, предикат BETWEEN можно переписать следующим образом:

<value> >= <value_1> AND <value> <= <value_2>

При использовании предиката BETWEEN в поисковых условиях DML запросов, оптимизатор Firebird может использовать индекс по искомому столбцу, если таковой доступен.

Example 1. Использование предиката BETWEEN
SELECT *
FROM EMPLOYEE
WHERE HIRE_DATE BETWEEN date '01.01.1992' AND CURRENT_DATE

LIKE

Доступно в

DSQL, PSQL, ESQL.

Синтаксис
<match value> [NOT] LIKE <pattern>
  [ESCAPE <escape character>]

<match value> ::= выражение символьного типа
<pattern> ::= шаблон поиска
<escape character> ::= символ экранирования

Предикат LIKE сравнивает выражение символьного типа с шаблоном, определённым во втором выражении.Чувствительность к регистру или диакритическим знакам при сравнении определяется используемым параметром сортировки (COLLATION).

При использовании оператора LIKE во внимание принимаются все символы строки-шаблона.Это касается так же начальных и конечных пробелов.Если операция сравнения в запросе должна вернуть все строки, содержащие строки LIKE 'абв ' (с символом пробела на конце), то строка, содержащая 'абв' (без пробела), не будет возвращена.

Трафаретные символы

В шаблоне, разрешается использование двух трафаретных символов:

  • символ процента (%) заменяет последовательность любых символов (число символов в последовательности может быть от 0 и более) в проверяемом значении;

  • символ подчёркивания (_), который можно применять вместо любого единичного символа в проверяемом значении.

Если проверяемое значение соответствует образцу с учётом трафаретных символов, то предикат истинен.

Использование управляющего символа в предложении ESCAPE

Если искомая строка содержит трафаретный символ, то следует задать управляющий символ в предложении ESCAPE.Этот управляющий символ должен использоваться в образце перед трафаретным символом, сообщая о том, что последний следует трактовать как обычный символ.

Примеры использования предиката LIKE
Example 1. Поиск строк начинающихся с заданной подстроки с использованеим предиката LIKE

Поиск номеров отделов, названия которых начинаются со слова “Software”

SELECT DEPT_NO
FROM DEPT
WHERE DEPT_NAME LIKE 'Software%';

В данном запросе может быть использован индекс, если он построен на поле DEPT_NAME.

Note
Оптимизация LIKE

В общем случае предикат LIKE не использует индекс.Однако если предикат принимает вид LIKE 'string%', то он будет преобразован в предикат STARTING WITH, который будет использовать индекс.Если вам необходимо выполнить поиск с начала строки, то вместо предиката LIKE рекомендуется использовать предикат STARTING WITH.

Example 2. Использование трафаретного символа “_” в предикате LIKE

Поиск сотрудников, имена которых состоят из 5 букв, начинающихся с букв “Sm” и заканчивающихся на “th”.В данном случае предикат будет истинен для имен “Smith” и “Smyth”.

SELECT
    first_name
FROM
    employee
WHERE first_name LIKE 'Sm_th'
Example 3. Поиск внутри строки с использованием предиката LIKE

Поиск всех заказчиков, в адресе которых содержится строка “Ростов”.

SELECT *
FROM CUSTOMER
WHERE ADDRESS LIKE '%Ростов%'
Tip

Если вам необходимо выполнить поиск внутри строки, то вместо предиката LIKE рекомендуется использовать предикат CONTAINING.

Example 4. Использование управляющего символа в предложении ESCAPE с предикатом `LIKE

Поиск таблиц, содержащих в имени знак подчёркивания.В данном случае в качестве управляющего символа задан символ “#”.

SELECT
  RDB$RELATION_NAME
FROM RDB$RELATIONS
WHERE RDB$RELATION_NAME LIKE '%#_%' ESCAPE '#'
См. также:

STARTING WITH, CONTAINING, SIMILAR TO.

STARTING WITH

Доступно в

DSQL, PSQL, ESQL.

Синтаксис
<value> [NOT] STARTING WITH <start-value>

Предикат STARTING WITH ищет строку, которая начинается с символов в его аргументе start-value.Чувствительность к регистру и ударению в STARTING WITH зависит от сортировки (COLLATION) первого аргумента value.

При использовании предиката STARTING WITH в поисковых условиях DML запросов, оптимизатор Firebird может использовать индекс по искомому столбцу, если он определён.

Example 1. Использование предиката STARTING WITH

Поиск сотрудников, фамилия которых начинается с “Jo”.

SELECT LAST_NAME, FIRST_NAME
FROM EMPLOYEE
WHERE LAST_NAME STARTING WITH 'Jo'
См. также:

LIKE.

CONTAINING

Доступно в

DSQL, PSQL, ESQL.

Синтаксис
<value> [NOT] CONTAINING <substring>

Оператор CONTAINING ищет строку или тип, подобный строке, отыскивая последовательность символов, которая соответствует его аргументу.Он может быть использован для алфавитно-цифрового (подобного строковому) поиска в числах и датах.Поиск CONTAINING не чувствителен к регистру.Тем не менее, если используется сортировка чувствительная к акцентам, то поиск будет чувствителен к акцентам.

При использовании оператора CONTAINING во внимание принимаются все символы строки.Это касается так же начальных и конечных пробелов.Если операция сравнения в запросе должна вернуть все строки, содержащие строки CONTAINING 'абв ' (с символом пробела на конце), то строка, содержащая 'абв' (без пробела), не будет возвращена.

При использовании предиката CONTAINING в поисковых условиях DML запросов, оптимизатор Firebird не может использовать индекс по искомому столбцу.

Example 1. Поиск подстроки с использованием предиката CONTAINING

Поиск проектов в именах, которых присутствует подстрока “Map”:

SELECT *
FROM PROJECT
WHERE PROJ_NAME CONTAINING 'map';

В данном случае будет возвращены две строки с именами “AutoMap” и “MapBrowser port”.

Example 2. Поиск внутри даты с использованием предиката CONTAINING

Поиск записей об изменении зарплат с датой содержащей число 84 (в данном случае изменения, которые произошли в 1984 году):

SELECT *
FROM SALARY_HISTORY
WHERE CHANGE_DATE CONTAINING 84;
См. также:

LIKE.

SIMILAR TO

Доступно в

DSQL, PSQL.

Синтаксис
string-expression [NOT] SIMILAR TO <pattern> [ESCAPE <escape-char>]

<pattern> ::= регулярное выражение SQL
<escape-char> ::= символ экранирования

Оператор SIMILAR TO проверяет соответствие строки с шаблоном регулярного выражения SQL.В отличие от некоторых других языков для успешного выполнения шаблон должен соответствовать всей строке — соответствие подстроки недостаточно.Если один из операндов имеет значение NULL, то и результат будет NULL.В противном случае результат является TRUE или FALSE.

Синтаксис регулярных выражений SQL

Следующий синтаксис определяет формат регулярного выражения SQL.Это полное и корректное его определение.Он является весьма формальным и довольно длинным и, вероятно, озадачивает тех, кто не имеет опыта работы с регулярными выражениями.Не стесняйтесь пропустить его и начать читать следующий раздел, Создание регулярных выражений, использующий подход от простого к сложному.

<regular expression> ::= <regular term> ['|' <regular term> ...]

<regular term> ::= <regular factor> ...

<regular factor> ::= <regular primary> [<quantifier>]

<quantifier> ::= ? | * | + | '{' <m> [,[<n>]] '}'

<m>, <n> ::= целые положительные числа, если присутвуют оба числа, то <m> <= <n>

<regular primary> ::=
    <character> | <character class> | %
  | (<regular expression>)

<character> ::= <escaped character> | <non-escaped character>

<escaped character> ::=
  <escape-char> <special character> | <escape-char> <escape-char>

<special character> ::= любой из символов []()|^-+*%_?{}

<non-escaped character> ::=
  любой символ за исключением <special character>
  и не эквивалентный <escape-char> (если задан)

<character class> ::=
    '_' | '[' <member> ... ']' | '[^' <non-member> ... ']'
  | '[' <member> ... '^' <non-member> ... ']'

<member>, <non-member> ::= <character> | <range> | <predefined class>

<range> ::= <character>-<character>

<predefined class> ::= '[:' <predefined class name> ':]'

<predefined class name> ::=
  ALPHA | UPPER | LOWER | DIGIT | ALNUM | SPACE | WHITESPACE
Создание регулярных выражений

В этом разделе представлены элементы и правила построения регулярных выражений SQL.

Символы

В регулярных выражениях большинство символов представляет сами себя, за исключением специальных символов (special character):

[ ] ( ) | ^ - + * % _ ? { }

... и управляющих символов (escaped character), если они заданы.

Регулярному выражению, не содержащему специальных или управляющих символов, соответствует только полностью идентичные строки (в зависимости от используемой сортировки). То есть это функционирует точно так же, как оператор “=”:

'Apple' SIMILAR TO 'Apple' -- TRUE
'Apples' SIMILAR TO 'Apple' -- FALSE
'Apple' SIMILAR TO 'Apples' -- FALSE
'APPLE' SIMILAR TO 'Apple' -- в зависимости от сортировки
Шаблоны

Известным SQL шаблонам ‘_’ и ‘%’ соответствует любой единственный символ и строка любой длины, соответственно:

'Birne' SIMILAR TO 'B_rne' -- TRUE
'Birne' SIMILAR TO 'B_ne' -- FALSE
'Birne' SIMILAR TO 'B%ne' -- TRUE
'Birne' SIMILAR TO 'Bir%ne%' -- TRUE
'Birne' SIMILAR TO 'Birr%ne' -- FALSE

Обратите внимание, что шаблон ‘%’ также соответствует пустой строке.

Классы символов

Набор символов, заключённый в квадратные скобки определяют класс символов.Символ в строке соответствует классу в шаблоне, если символ является элементом класса:

'Citroen' SIMILAR TO 'Cit[arju]oen' -- TRUE
'Citroen' SIMILAR TO 'Ci[tr]oen' -- FALSE
'Citroen' SIMILAR TO 'Ci[tr][tr]oen' -- TRUE

Как видно из второй строки классу только соответствует единственный символ, а не их последовательность.

Два символа, соединённые дефисом, в определении класса определяют диапазон.Диапазон для активного сопоставления включает в себя эти два конечных символа и все символы, находящиеся между ними.Диапазоны могут быть помещены в любом месте в определении класса без специальных разделителей, чтобы сохранить в классе и другие символы.

'Datte' SIMILAR TO 'Dat[q-u]e' -- TRUE
'Datte' SIMILAR TO 'Dat[abq-uy]e' -- TRUE
'Datte' SIMILAR TO 'Dat[bcg-km-pwz]e' -- FALSE
Предопределённые классы символов

Следующие предопределенные классы символов также могут использоваться в определении класса:

[:ALPHA:]

Латинские буквы a…​z и A…​Z.Этот класс также включает символы с диакритическими знаками при нечувствительных к акцентам сортировках.

[:DIGIT:]

Десятичные цифры 0…​9.

[:ALNUM:]

Объединение [:ALPHA:] и [:DIGIT:].

[:UPPER:]

Прописные (в верхнем регистре) латинские буквы A…​Z.Также включает в себя символы в нижнем регистре при нечувствительных к регистру сортировках и символы с диакритическими знаками при нечувствительных к акцентам сортировках.

[:LOWER:]

Строчные (в нижнем регистре) латинские буквы a…​z.Также включает в себя символы в верхнем регистре при нечувствительных к регистру сортировках и символы с диакритическими знаками при нечувствительных к акцентам сортировках.

[:SPACE:]

Символ пробела (ASCII 32).

[:WHITESPACE:]

Горизонтальная табуляция (ASCII 9), перевод строки (ASCII 10), вертикальная табуляция (ASCII 11), разрыв страницы (ASCII 12), возврат каретки (ASCII 13) и пробел (ASCII 32).

Включение в оператор SIMILAR TO предопределённого класса имеет тот же эффект, как и включение всех его элементов.Использование предопределённых классов допускается только в пределах определения класса.Если вам нужно сопоставление только с предопределённым классом и ничего больше, то поместите дополнительную пару скобок вокруг него.

'Erdbeere' SIMILAR TO 'Erd[[:ALNUM:]]eere' -- TRUE
'Erdbeere' SIMILAR TO 'Erd[[:DIGIT:]]eere' -- FALSE
'Erdbeere' SIMILAR TO 'Erd[a[:SPACE:]b]eere' -- TRUE
'Erdbeere' SIMILAR TO '[[:ALPHA:]]' -- FALSE
'E' SIMILAR TO '[[:ALPHA:]]' -- TRUE

Если определение класса запускается со знаком вставки (^), то все, что следует за ним, исключается из класса.Все остальные символы проверяются.

'Framboise' SIMILAR TO 'Fra[^ck-p]boise' -- FALSE
'Framboise' SIMILAR TO 'Fr[^a][^a]boise' -- FALSE
'Framboise' SIMILAR TO 'Fra[^[:DIGIT:]]boise' -- TRUE

Если знак вставки (^) находится не в начале последовательности, то класс включает в себя все символы до него и исключает символы после него.

'Grapefruit' SIMILAR TO 'Grap[a-m^f-i]fruit' -- TRUE
'Grapefruit' SIMILAR TO 'Grap[abc^xyz]fruit' -- FALSE
'Grapefruit' SIMILAR TO 'Grap[abc^de]fruit' -- FALSE
'Grapefruit' SIMILAR TO 'Grap[abe^de]fruit' -- FALSE
'3' SIMILAR TO '[[:DIGIT:]^4-8]' -- TRUE
'6' SIMILAR TO '[[:DIGIT:]^4-8]' -- FALSE

Наконец, уже упомянутый подстановочный знак ‘_’ является собственным классом символов, соответствуя любому единственному символу.

Кванторы

Вопросительный знак (‘?’) сразу после символа или класса указывает на то, что для соответствия предыдущий элемент должен встретиться 0 или 1 раз:

'Hallon' SIMILAR TO 'Hal?on' -- FALSE
'Hallon' SIMILAR TO 'Hal?lon' -- TRUE
'Hallon' SIMILAR TO 'Halll?on' -- TRUE
'Hallon' SIMILAR TO 'Hallll?on' -- FALSE
'Hallon' SIMILAR TO 'Halx?lon' -- TRUE
'Hallon' SIMILAR TO 'H[a-c]?llon[x-z]?' -- TRUE

Звёздочка (‘*’) сразу после символа или класса указывает на то, что для соответствия предыдущий элемент должен встретиться 0 или более раз:

'Icaque' SIMILAR TO 'Ica*que' -- TRUE
'Icaque' SIMILAR TO 'Icar*que' -- TRUE
'Icaque' SIMILAR TO 'I[a-c]*que' -- TRUE
'Icaque' SIMILAR TO '_*' -- TRUE
'Icaque' SIMILAR TO '[[:ALPHA:]]*' -- TRUE
'Icaque' SIMILAR TO 'Ica[xyz]*e' -- FALSE

Знак плюс (‘+’) сразу после символа или класса указывает на то, что для соответствия предыдущий элемент должен встретиться 1 или более раз:

'Jujube' SIMILAR TO 'Ju_+' -- TRUE
'Jujube' SIMILAR TO 'Ju+jube' -- TRUE
'Jujube' SIMILAR TO 'Jujuber+' -- FALSE
'Jujube' SIMILAR TO 'J[jux]+be' -- TRUE
'Jujube' SIMILAR TO 'J[[:DIGIT:]]+ujube' -- FALSE

Если символ или класс сопровождаются числом, заключённым в фигурные скобки (‘{’ и ‘}’), то для соответствия необходимо повторение элемента точно это число раз:

'Kiwi' SIMILAR TO 'Ki{2}wi' -- FALSE
'Kiwi' SIMILAR TO 'K[ipw]{2}i' -- TRUE
'Kiwi' SIMILAR TO 'K[ipw]{2}' -- FALSE
'Kiwi' SIMILAR TO 'K[ipw]{3}' -- TRUE

Если число сопровождается запятой (‘,’), то для соответствия необходимо повторение элемента как минимум это число раз:

'Limone' SIMILAR TO 'Li{2,}mone' -- FALSE
'Limone' SIMILAR TO 'Li{1,}mone' -- TRUE
'Limone' SIMILAR TOto 'Li[nezom]{2,}' -- TRUE

Если фигурные скобки содержат два числа (m и n), разделённые запятой, и второе число больше первого, то для соответствия элемент должен быть повторен, как минимум, m раз и не больше n раз:

'Mandarijn' SIMILAR TO 'M[a-p]{2,5}rijn' -- TRUE
'Mandarijn' SIMILAR TO 'M[a-p]{2,3}rijn' -- FALSE
'Mandarijn' SIMILAR TO 'M[a-p]{2,3}arijn' -- TRUE

Кванторы ‘?’, ‘*’ и ‘+’ являются сокращением для {0,1}, {0,} и {1,}, соответственно.

Термин ИЛИ

В условиях регулярных выражений можно использовать оператор ИЛИ ‘|’. Соответствие произошло, если строка параметра соответствует, по крайней мере, одному из условий:

'Nektarin' SIMILAR TO 'Nek|tarin' -- FALSE
'Nektarin' SIMILAR TO 'Nektarin|Persika' -- TRUE
'Nektarin' SIMILAR TO 'M_+|N_+|P_+' -- TRUE
Подвыражения

Одна или более частей регулярного выражения могут быть сгруппированы в подвыражения (также называемые подмасками). Для этого их нужно заключить в круглые скобки (‘(’ и ‘)’):

'Orange' SIMILAR TO 'O(ra|ri|ro)nge' -- TRUE
'Orange' SIMILAR TO 'O(r[a-e])+nge' -- TRUE
'Orange' SIMILAR TO 'O(ra){2,4}nge' -- FALSE
'Orange' SIMILAR TO 'O(r(an|in)g|rong)?e' -- TRUE
Экранирование специальных символов

Для исключения из процесса сопоставления специальных символов (которые часто встречаются в регулярных выражениях) их надо экранировать.Специальных символов экранирования по умолчанию нет — их при необходимости определяет пользователь:

'Peer (Poire)' SIMILAR TO 'P[^ ]+ \(P[^ ]+\)' ESCAPE '\' -- TRUE
'Pera [Pear]' SIMILAR TO 'P[^ ]+ #[P[^ ]+#]' ESCAPE '#' -- TRUE
'Paron-Appledryck' SIMILAR TO 'P%$-A%' ESCAPE '$' -- TRUE
'Parondryck' SIMILAR TO 'P%--A%' ESCAPE '-' -- FALSE

IS DISTINCT FROM

Доступно в

DSQL, PSQL.

Синтаксис
<operand1> IS [NOT] DISTINCT FROM <operand2>

Два операнда считают DISTINCT (различными), если они имеют различные значения, или если одно из них — NULL, а другое нет.Они считаются NOT DISTINCT (равными), если имеют одинаковые значения или оба имеют значение NULL.

IS [NOT] DISTINCT FROM всегда возвращает TRUE или FALSE и никогда UNKNOWN (NULL) (неизвестное значение). Операторы ‘=’ и ‘<>’, наоборот, вернут UNKNOWN (NULL), если один или оба операнда имеют значение NULL.

Table 1. Результаты выполнения различных операторов сравнения

Характеристики операнда

Результаты различных операторов

=

IS NOT DISTINCT FROM

<>

IS DISTINCT FROM

Одинаковые значения

TRUE

TRUE

FALSE

FALSE

Различные значения

FALSE

FALSE

TRUE

TRUE

Оба NULL

UNKNOWN

TRUE

UNKNOWN

FALSE

Одно NULL

UNKNOWN

FALSE

UNKNOWN

TRUE

Example 1. Использование предиката IS [NOT] DISTINCT FROM
SELECT ID, NAME, TEACHER
FROM COURSES
WHERE START_DAY IS NOT DISTINCT FROM END_DAY

IF (NEW.JOB IS DISTINCT FROM OLD.JOB) THEN
  POST_EVENT 'JOB_CHANGED';

Логический IS [NOT]

Доступно в

DSQL, PSQL.

Синтаксис
<value> IS [NOT] {TRUE | FALSE | UNKNOWN}

Оператор IS проверяет, что выражение в левой части соответствует логическому значению в правой части.Выражение в левой части должно быть логического типа, иначе будет выдана ошибка.

Для логического типа данных предикат IS [NOT] UNKNOWN эквивалентен IS [NOT] NULL.

Note
Замечание:

В правой части предиката могут быть использованы только литералы TRUE, FALSE, UNKNOWN, но не выражения.

Example 1. Использование оператора IS с логическим типом данных
-- Проверка FALSE значения
SELECT * FROM TBOOL WHERE BVAL IS FALSE
ID           BVAL
============ =======
2            <false>
-- Проверка UNKNOWN значения
SELECT * FROM TBOOL WHERE BVAL IS UNKNOWN
ID           BVAL
============ =======
3            <null>

IS [NOT] NULL

Доступно в

DSQL, PSQL.

Синтаксис
<value> IS [NOT] NULL

Поскольку NULL не является значением, эти операторы не являются операторами сравнения.Оператор IS [NOT] NULL проверяет, что выражение слева имеет значение (IS NOT NULL) или не имеет значения (IS NULL)

Example 1. Использование предиката IS [NOT] NULL

Поиск записей о продажах, для которых не установлена дата отгрузки:

SELECT *
FROM SALES
WHERE SHIP_DATE IS NULL;

Предикаты существования

В эту группу предикатов включены предикаты, которые используют подзапросы и передают значения для всех видов утверждений в условиях поиска.Предикаты существования называются так потому, что они различными способами проверяют существование или отсутствие результатов подзапросов.

EXISTS

Доступно в

DSQL, PSQL, ESQL.

Синтаксис
[NOT] EXISTS (<select_stmt>)

Предикат EXISTS использует подзапрос в качестве аргумента.Если результат подзапроса будет содержать хотя бы одну запись, то предикат оценивается как истинный (TRUE), в противном случае предикат оценивается как ложный (FALSE).

Результат подзапроса может содержать несколько столбцов, поскольку значения не проверяются, а просто фиксируется факт наличия строк результата.Данный предикат может принимать только два значения: истина (TRUE) и ложь (FALSE).

Предикат NOT EXISTS возвращает FALSE, если результат подзапроса будет содержать хотя бы одну запись, в противном случае предикат вернёт TRUE.

Example 1. Предикат EXISTS

Найти тех сотрудников, у которых есть проекты.

SELECT *
FROM employee
WHERE EXISTS (SELECT *
              FROM
                employee_project ep
              WHERE
                ep.emp_no = employee.emp_no)
Example 2. Предикат NOT EXISTS

Найти тех сотрудников, у которых нет проектов.

SELECT *
FROM employee
WHERE NOT EXISTS (SELECT *
                  FROM
                    employee_project ep
                  WHERE
                    ep.emp_no = employee.emp_no)

IN

Доступно в

DSQL, PSQL, ESQL.

Синтаксис
<value> [NOT] IN (<select_stmt> | <value_list>)

<value_list> ::= <value_1> [, <value_2> ...]

Предикат IN проверяет, присутствует ли значение выражения слева в указанном справа наборе значений.Набор значений не может превышать 1500 элементов.Предикат IN может быть переписан в следующей эквивалентной форме:

(<value> = <value_1> [OR <value> = <value_2> ...])

При использовании предиката IN в поисковых условиях DML запросов, оптимизатор Firebird может использовать индекс по искомому столбцу, если он определён.

Во второй форме предикат IN проверяет, присутствует (или отсутствует, при использовании NOT IN) ли значение выражения слева в результате выполнения подзапроса справа.Результат подзапроса может содержать только один столбец, иначе будет выдана ошибка“count of column list and variable list do not match”.

Запросы с использованием предиката IN с подзапросом, можно переписать на аналогичный запрос с использованием предиката EXISTS.Например, следующий запрос:

SELECT
  model, speed, hd
FROM PC
WHERE
  model IN (SELECT model
            FROM product
            WHERE maker = 'A');

Можно переписать на аналогичный запрос с использованием предиката EXISTS:

SELECT
  model, speed, hd
FROM PC
WHERE
  EXISTS (SELECT *
          FROM product
          WHERE maker = 'A'
            AND product.model = PC.model);

Однако, запрос с использованием NOT IN не всегда даст тот же результат, что запрос NOT EXISTS.Причина заключается в том, что предикат EXISTS всегда возвращает TRUE или FALSE, тогда как предикат IN может вернуть NULL в следующих случаях:

  1. Когда проверяемое значение равно NULL и список в IN не пуст.

  2. Когда проверяемое значение не имеет совпадений в списке IN и одно из значений является NULL.

В этих двух случаях предикат IN вернёт NULL, в то время как соответствующий предикат EXISTS вернёт FALSE.В поисковых условиях или операторе IF оба результата обозначают “провал” и обрабатываются одинаково.

Однако на тех же данных NOT IN вернёт NULL, в то время как EXISTS вернёт TRUE, что приведёт к противоположному результату.

Это можно продемонстрировать следующим примером.

Предположим у вас есть такой запрос:

-- Ищем людей, которые не родились в тот же день, что
-- известные жители Нью-Йорка
SELECT P1.name AS NAME
FROM Personnel P1
WHERE P1.birthday NOT IN (SELECT C1.birthday
                          FROM Celebrities C1
                          WHERE С1.birthcity = 'New York');

Можно предположить, что аналогичный результат даст запрос с использованием предиката NOT EXISTS:

-- Ищем людей, которые не родились в тот же день, что
-- известные жители Нью-Йорка
SELECT P1.name AS NAME
FROM Personnel P1
WHERE NOT EXISTS (SELECT *
                  FROM Celebrities C1
                  WHERE C1.birthcity = 'New York'
                    AND C1.birthday = P1.birthday);

Допустим, что в Нью-Йорке всего один известный житель, и его дата рождения неизвестна.При использовании предиката EXISTS подзапрос внутри него не выдаст результатов, так как при сравнении дат рождения с NULL результатом будет UNKNOWN.Это приведёт к тому, что результат предиката NOT EXISTS будет истинен для каждой строки основного запроса.В то время как результатом предиката NOT IN будет UNKNOWN и ни одна строка не будет выведена.

Example 1. Предикат IN

Найти сотрудников с именами “Pete”, “Ann” и “Roger”:

SELECT *
FROM EMPLOYEE
WHERE FIRST_NAME IN ('Pete', 'Ann', 'Roger');
Example 2. Поисковый предикат IN

Найти все компьютеры, для которых существуют модели с производителем начинающимися на букву “A”:

SELECT
  model, speed, hd
FROM PC
WHERE
  model IN (SELECT model
            FROM product
            WHERE maker STARTING WITH 'A');
См. также:

EXISTS.

SINGULAR

Доступно в

DSQL, PSQL, ESQL.

Синтаксис
[NOT] SINGULAR (<select_stmt>)

Предикат SINGULAR использует подзапрос в качестве аргумента и оценивает его как истинный, если подзапрос возвращает одну и только одну строку результата, в противном случае предикат оценивается как ложный.Результат подзапроса может содержать несколько столбцов, поскольку значения не проверяются.Данный предикат может принимать только два значения: истина (TRUE) и ложь (FALSE).

Example 1. Предикат SINGULAR

Найти тех сотрудников, у которых есть только один проект.

SELECT *
FROM employee
WHERE SINGULAR (SELECT *
                FROM
                  employee_project ep
                WHERE
                  ep.emp_no = employee.emp_no)

Количественные предикаты подзапросов

Квантором называется логический оператор, задающий количество объектов, для которых данное утверждение истинно.Это логическое количество, а не числовое; оно связывает утверждение с полным множеством возможных объектов.Такие предикаты основаны на формальных логических квантификаторах общности и существования, которые распознаются формальной логикой.

В выражениях подзапросов количественные предикаты позволяют сравнивать отдельные значения с результатами подзапросов; их общая форма:

<value expression> <comparison operator> <quantifier> <subquery>

ALL

Доступно в

DSQL, PSQL.

Синтаксис
<value> <op> ALL (<select_stmt>)

При использовании квантора ALL, предикат является истинным, если каждое значение выбранное подзапросом удовлетворяет условию в предикате внешнего запроса.Если подзапрос не возвращает ни одной строки, то предикат автоматически считается верным.

Example 1. Квантор ALL

Вывести только тех заказчиков, чьи оценки выше, чем у каждого заказчика в Париже.

SELECT *
FROM Customers
WHERE rating > ALL
      (SELECT rating
       FROM Customers
       WHERE city = 'Paris')
Important

Если подзапрос возвращает пустое множество, то предикат будет истинен для каждого левостороннего значения, независимо от оператора.Это может показаться странным и противоречивым, потому что в этом случае каждое левостороннее значение рассматривается как одновременно больше, меньше, равное и неравное любому значению из правого потока.

Тем не менее это нормально согласуется с формальной логикой: если множество пусто, то предикат верен 0 раз, т.е.для каждой строки в множестве.

ANY и SOME

Доступно в

DSQL, PSQL.

Синтаксис
<value> <op> {ANY | SOME} (<select_stmt>)

Эти два квантора идентичны по поведению.Очевидно, оба представлены в стандарте SQL для взаимозаменяемого использования с целью улучшения читаемости операторов.При использовании квантора ANY или SOME, предикат является истинным, если любое из значений выбранное подзапросом удовлетворяет условию в предикате внешнего запроса.Если подзапрос не возвращает ни одной строки, то предикат автоматически считается ложным.

Example 1. Квантор ANY

Вывести только тех заказчиков, чьи оценки выше, чем у какого-либо заказчика в Риме.

SELECT *
FROM Customers
WHERE rating > ANY
      (SELECT rating
       FROM Customers
       WHERE city = 'Rome')