10.5. UNION
, CASE
и связанные конструкции
SQL-конструкция UNION
взаимодействует с системой типов, так как ей приходится объединять значения возможно различных типов в единый результирующий набор. Алгоритм разрешения типов при этом применяется независимо к каждому отдельному столбцу запроса. Подобным образом различные типы сопоставляются при выполнении INTERSECT
и EXCEPT
сопоставляют различные типы подобно UNION
. По такому же алгоритму сопоставляют типы выражений и определяют тип своего результата конструкции CASE
, ARRAY
, VALUES
, GREATEST
и LEAST
.
Разрешение типов для UNION
, CASE
и связанных конструкций
Если все данные одного типа и это не тип
unknown
, выбрать его.Если тип данных — домен, далее считать их типом базовый тип домена. [11]
Если все данные типа
unknown
, выбрать для результата типtext
(предпочитаемый для категории string). В противном случае значенияunknown
игнорируются.Если известные типы входных данных оказываются не из одной категории, констатировать неудачу.
Выбрать первый известный предпочитаемый тип из этой категории, если такой есть.
В противном случае выбрать последний известный тип, в который можно неявно преобразовать все данные предшествующих известных типов. (Такой тип есть всегда, в крайнем случае этому условию удовлетворяет первый тип.)
Привести все данные к выбранном типу. Констатировать неудачу, если для каких-либо данных преобразование в этот тип невозможно.
Ниже это проиллюстрировано на примерах.
Пример 10.10. Разрешение типов с частичным определением в Union
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
и целочисленное значение 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
Эта ошибка возникает из-за того, что Postgres Pro воспринимает множественные UNION
как пары с вложенными операциями, то есть как запись
(SELECT NULL UNION SELECT NULL) UNION SELECT 1;
Внутренний UNION
разрешается как выдающий тип text
, согласно правилам, приведённым выше. Затем внешний UNION
получает на вход типы text
и integer
, что и приводит к показанной ошибке. Эту проблему можно устранить, сделав так, чтобы у самого левого UNION
минимум с одной стороны были данные желаемого типа результата.
Операции INTERSECT
и EXCEPT
также разрешаются по парам. Однако остальные конструкции, описанные в этом разделе, рассматривают все входные данные сразу.
[11] Так же, как домены воспринимаются при выборе операторов и функций, доменные типы могут сохраняться в конструкции UNION
или подобной, если пользователь позаботится о том, чтобы все входные данные приводились к этому типу явно или неявно. В противном случае предпочтение будет отдано базовому типу домена.