10.5. UNION, CASE и связанные конструкции#

10.5. UNION, CASE и связанные конструкции

10.5. UNION, CASE и связанные конструкции #

Соединения UNION в SQL должны соответствовать, возможно, различным типам данных, чтобы стать единственным набором результатов. Алгоритм разрешения применяется отдельно к каждому столбцу вывода запроса с объединением. Конструкции INTERSECT и EXCEPT разрешают различные типы данных так же, как и UNION. Некоторые другие конструкции, включая CASE, ARRAY, VALUES и функции GREATEST и LEAST, используют идентичный алгоритм для сопоставления их составных выражений и выбора типа данных результата.

Определение типа для UNION, CASE и связанных конструкций

  1. Если все входные данные одного типа и это не unknown, разрешите как этот тип.

  2. Если какой-либо входной параметр является типом домена, считайте его базовым типом домена для всех последующих шагов. [12]

  3. Если все входные данные имеют тип unknown, разрешите как тип text (предпочтительный тип для категории строк). В противном случае, входные данные типа unknown игнорируются для целей остальных правил.

  4. Если неизвестные входные данные не являются одного типа, не удалось.

  5. Выберите первый неизвестный тип ввода в качестве типа-кандидата, затем рассмотрите каждый другой неизвестный тип ввода, слева направо. [13] Если тип кандидата может быть неявно преобразован в другой тип, но не наоборот, выберите другой тип в качестве нового типа кандидата. Затем продолжайте рассматривать оставшиеся входные данные. Если на любом этапе этого процесса выбран предпочтительный тип, прекратите рассмотрение дополнительных входных данных.

  6. Преобразуйте все входные данные в конечный тип кандидата. Если нет неявного преобразования из заданного типа входных данных в тип кандидата, то произойдет сбой.

Следуют некоторые примеры.

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