9.25. Сравнение табличных строк и массивов #
В этом разделе описываются несколько специальных конструкций, позволяющих сравнивать группы значений. Синтаксис этих конструкций связан с формами выражений с подзапросами, описанными в предыдущем разделе, а отличаются они отсутствием подзапросов. Конструкции, в которых в качестве подвыражений используются массивы, являются расширениями Postgres Pro; все остальные формы соответствуют стандарту SQL. Все описанные здесь выражения возвращают логические значения (true/false).
9.25.1. IN
#
выражение
IN (значение
[, ...])
Справа в скобках записывается список выражений. Результатом будет «true», если значение левого выражения равняется одному из значений выражений в правой части. Эту конструкцию можно считать краткой записью условия
выражение
=значение1
ORвыражение
=значение2
OR ...
Заметьте, что если результатом выражения слева оказывается NULL или равных значений справа не находится, а хотя бы одно из значений справа равно NULL, конструкция IN
возвращает NULL, а не false. Это соответствует принятым в SQL правилам сравнения переменных со значениями NULL.
9.25.2. NOT IN
#
выражение
NOT IN (значение
[, ...])
Справа в скобках записывается список выражений. Результатом будет «true», если значение левого выражения не равно ни одному из значений выражений в правой части. Эту конструкцию можно считать краткой записью условия
выражение
<>значение1
ANDвыражение
<>значение2
AND ...
Заметьте, что если результатом выражения слева оказывается NULL или равных значений справа не находится, а хотя бы одно из значений справа равно NULL, конструкция NOT IN
возвращает NULL, а не true, как можно было бы наивно полагать. Это соответствует принятым в SQL правилам сравнения переменных со значениями NULL.
Подсказка
Выражения x NOT IN y
и NOT (x IN y)
полностью равнозначны. Учитывая, что значения NULL могут ввести в заблуждение начинающих скорее в конструкции NOT IN
, чем в IN
, лучше формулировать условия так, чтобы в них было как можно меньше отрицаний.
9.25.3. ANY
/SOME
(с массивом) #
выражение
оператор
ANY (выражение массива
)выражение
оператор
SOME (выражение массива
)
Справа в скобках записывается выражение, результатом которого является массив. Вычисленное значение левого выражения сравнивается с каждым элементом этого массива с применением заданного оператора
условия, который должен выдавать логическое значение. Результатом ANY
будет «true», если для какого-либо элемента условие истинно, и «false» в противном случае (в том числе, и когда массив оказывается пустым).
Если значением массива оказывается NULL, результатом ANY
также будет NULL. Если NULL получен в левой части, результатом ANY
обычно тоже будет NULL (хотя оператор нестрогого сравнения может выдать другой результат). Кроме того, если массив в правой части содержит элементы NULL и ни c одним из элементов условие не выполняется, результатом ANY
будет NULL, а не false (опять же, если используется оператор строгого сравнения). Это соответствует принятым в SQL правилам сравнения переменных со значениями NULL.
Ключевое слово SOME
является синонимом ANY
.
9.25.4. ALL
(с массивом) #
выражение
оператор
ALL (выражение массива
)
Справа в скобках записывается выражение, результатом которого является массив. Вычисленное значение левого выражения сравнивается с каждым элементом этого массива с применением заданного оператора
условия, который должен выдавать логическое значение. Результатом ALL
будет «true», если для всех элементов условие истинно (или массив не содержит элементов), и «false», если находятся строки, для которых оно ложно.
Если значением массива оказывается NULL, результатом ALL
также будет NULL. Если NULL получен в левой части, результатом ALL
обычно тоже будет NULL (хотя оператор нестрогого сравнения может выдать другой результат). Кроме того, если массив в правой части содержит элементы NULL и при этом нет элементов, с которыми условие не выполняется, результатом ALL
будет NULL, а не true (опять же, если используется оператор строгого сравнения). Это соответствует принятым в SQL правилам сравнения переменных со значениями NULL.
9.25.5. Сравнение конструкторов строк #
конструктор_строки
оператор
конструктор_строки
С обеих сторон представлены конструкторы строк (они описываются в Подразделе 4.2.13). При этом данные конструкторы должны содержать одинаковое число полей. Заданный оператор
применяется к каждой паре соответствующих полей. (Поскольку поля могут быть разных типов, для каждой пары может быть выбран отдельный конкретный оператор.) Все выбранные операторы должны быть членами некоторого класса операторов B-дерева или быть обратными члену класса операторов B-дерева =
. Сравнения конструкторов строк возможны с оператором
=
, <>
, <
, <=
, >
или >=
, или имеющим аналогичную семантику.
Сравнения =
и <>
несколько отличаются от других. С этими операторами две строки считаются равными, если все их соответствующие поля не равны NULL и равны между собой, и неравными, если какие-либо соответствующие их поля не NULL и не равны между собой. В противном случае результатом сравнения будет неопределённость (NULL).
С операторами <
, <=
, >
и >=
элементы строк сравниваются слева направо до тех пор, пока не будет найдена пара неравных элементов или значений NULL. Если любым из элементов пары оказывается NULL, результатом сравнения будет неопределённость (NULL), в противном случае результат всего выражения определяется результатом сравнения этих двух элементов. Например, результатом ROW(1,2,NULL) < ROW(1,3,0)
будет true, а не NULL, так как третья пара элементов не принимается в рассмотрение.
конструктор_строки
IS DISTINCT FROMконструктор_строки
Эта конструкция похожа на сравнение строк с оператором <>
, но со значениями NULL она выдаёт не NULL. Любое значение NULL для неё считается неравным (отличным от) любому значению не NULL, а два NULL считаются равными (не различными). Таким образом, результатом такого выражения будет true или false, но не NULL.
конструктор_строки
IS NOT DISTINCT FROMконструктор_строки
Эта конструкция похожа на сравнение строк с оператором =
, но со значениями NULL она выдаёт не NULL. Любое значение NULL для неё считается неравным (отличным от) любому значению не NULL, а два NULL считаются равными (не различными). Таким образом, результатом такого выражения всегда будет true или false, но не NULL.
9.25.6. Сравнение составных типов #
запись
оператор
запись
Стандарт SQL требует, чтобы при сравнении строк возвращался NULL, если результат зависит от сравнения двух значений NULL или значения NULL и не NULL. Postgres Pro выполняет это требование только при сравнении строк, созданных конструкторами (как описано в Подразделе 9.25.5), или строки, созданной конструктором, со строкой результата подзапроса (как было описано в Разделе 9.24). В других контекстах при сравнении полей составных типов два значения NULL считаются равными, а любое значение не NULL полагается меньшим NULL. Это отклонение от правила необходимо для полноценной реализации сортировки и индексирования составных типов.
После вычисления каждой стороны они сравниваются по строкам. Сравнения составных типов возможны с оператором
=
, <>
, <
, <=
, >
или >=
, либо другим подобным. (Точнее, оператором сравнения строк может быть любой оператор, входящий в класс операторов B-дерева, либо обратный к оператору =
, входящему в класс операторов B-дерева.) По умолчанию вышеперечисленные операторы действуют так же, как выражение IS [ NOT ] DISTINCT FROM
для конструкторов строк (см. Подраздел 9.25.5).
Для поддержки сравнения строк с элементами, для которых не определён класс операторов B-дерева по умолчанию, введены следующие операторы: *=
, *<>
, *<
, *<=
, *>
и *>=
. Эти операторы сравнивают внутреннее двоичное представление двух строк. Учтите, что две строки могут иметь различное двоичное представление, даже когда при сравнении оператором равенства считаются равными. Порядок строк с такими операторами детерминирован, но не несёт смысловой нагрузки. Данные операторы не предназначены для обычных запросов; они применяются внутри системы для материализованных представлений и могут быть полезны для других специальных целей, например для репликации или исключения дубликатов в B-дереве (см. Подраздел 64.1.4.3).