10.5. UNION, CASE и связанные конструкции#
10.5. UNION
, CASE
и связанные конструкции #
Соединения UNION
в SQL должны соответствовать, возможно, различным типам данных, чтобы стать единственным набором результатов. Алгоритм разрешения применяется отдельно к каждому столбцу вывода запроса с объединением. Конструкции INTERSECT
и EXCEPT
разрешают различные типы данных так же, как и UNION
. Некоторые другие конструкции, включая CASE
, ARRAY
, VALUES
и функции GREATEST
и LEAST
, используют идентичный алгоритм для сопоставления их составных выражений и выбора типа данных результата.
Определение типа для UNION
, CASE
и связанных конструкций
Если все входные данные одного типа и это не
unknown
, разрешите как этот тип.Если какой-либо входной параметр является типом домена, считайте его базовым типом домена для всех последующих шагов. [12]
Если все входные данные имеют тип
unknown
, разрешите как типtext
(предпочтительный тип для категории строк). В противном случае, входные данные типаunknown
игнорируются для целей остальных правил.Если неизвестные входные данные не являются одного типа, не удалось.
Выберите первый неизвестный тип ввода в качестве типа-кандидата, затем рассмотрите каждый другой неизвестный тип ввода, слева направо. [13] Если тип кандидата может быть неявно преобразован в другой тип, но не наоборот, выберите другой тип в качестве нового типа кандидата. Затем продолжайте рассматривать оставшиеся входные данные. Если на любом этапе этого процесса выбран предпочтительный тип, прекратите рассмотрение дополнительных входных данных.
Преобразуйте все входные данные в конечный тип кандидата. Если нет неявного преобразования из заданного типа входных данных в тип кандидата, то произойдет сбой.
Следуют некоторые примеры.
Пример 10.10. Определение типов с недостаточно определенными типами в объединении
SELECT text 'a' AS "text" UNION SELECT 'b'; text ------ a b (2 rows)
Здесь неизвестный литерал типа 'b'
будет преобразован в тип text
.
Пример 10.11. Определение типов в простом объединении
SELECT 1.2 AS "numeric" UNION SELECT 1; numeric --------- 1 1.2 (2 rows)
Литерал 1.2
имеет тип numeric
,
а значение integer
1
может быть неявно приведено к типу
numeric
, поэтому используется этот тип.
Пример 10.12. Определение типов в транспонированном объединении
SELECT 1 AS "real" UNION SELECT CAST('2.2' AS REAL); real ------ 1 2.2 (2 rows)
Здесь, поскольку тип real
не может быть неявно приведен к типу integer
,
но тип integer
может быть неявно приведен к типу real
, результат объединения
типов разрешается как real
.
Пример 10.13. Определение типов во вложенном объединении
SELECT NULL UNION SELECT NULL UNION SELECT 1; ERROR: UNION types text and integer cannot be matched
Эта ошибка возникает потому, что Tantor BE рассматривает
несколько UNION
как вложенные попарные операции;
то есть, этот ввод эквивалентен
(SELECT NULL UNION SELECT NULL) UNION SELECT 1;
Внутренний UNION
разрешается как вывод типа text
, согласно указанным выше правилам. Затем внешний UNION
имеет входы типов text
и integer
, что приводит к наблюдаемой ошибке. Проблему можно исправить, убедившись, что самый левый UNION
имеет хотя бы один вход желаемого типа результата.
INTERSECT
и EXCEPT
операции также разрешаются попарно. Однако, другие конструкции, описанные в этом разделе, рассматривают все свои входные данные в одном шаге разрешения.
[12]
В некотором роде, как и обработка входных данных домена для операторов и функций, такое поведение позволяет сохранить тип домена через UNION
или аналогичную конструкцию, при условии, что пользователь аккуратно обеспечивает, чтобы все входные данные были неявно или явно этого точного типа. В противном случае будет использоваться базовый тип домена.
[13]
Для исторических причин CASE
рассматривает свой ELSE
блок (если есть) как “первый” вход, а затем рассматривает THEN
блоки. Во всех остальных случаях “слева направо” означает порядок, в котором выражения появляются в тексте запроса.