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 блоки. Во всех остальных случаях “слева направо” означает порядок, в котором выражения появляются в тексте запроса.