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