9.25. Сравнение табличных строк и массивов #
В этом разделе описываются несколько специальных конструкций, позволяющих сравнивать группы значений. Синтаксис этих конструкций связан с формами выражений с подзапросами, описанными в предыдущем разделе, а отличаются они отсутствием подзапросов. Конструкции, в которых в качестве подвыражений используются массивы, являются расширениями Postgres Pro; все остальные формы соответствуют стандарту SQL. Все описанные здесь выражения возвращают логические значения (true/false).
9.25.1. IN #
выражениеIN (значение[, ...])
Справа в скобках записывается список выражений. Результатом будет «true», если значение левого выражения равняется одному из значений выражений в правой части. Эту конструкцию можно считать краткой записью условия
выражение=значение1ORвыражение=значение2OR ...
Заметьте, что если результатом выражения слева оказывается NULL или равных значений справа не находится, а хотя бы одно из значений справа равно NULL, конструкция IN возвращает NULL, а не false. Это соответствует принятым в SQL правилам сравнения переменных со значениями NULL.
9.25.2. NOT IN #
выражениеNOT IN (значение[, ...])
Справа в скобках записывается список выражений. Результатом будет «true», если значение левого выражения не равно ни одному из значений выражений в правой части. Эту конструкцию можно считать краткой записью условия
выражение<>значение1ANDвыражение<>значение2AND ...
Заметьте, что если результатом выражения слева оказывается 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-дереве (см. Подраздел 62.1.4.3).