UNION ALL два SELECT с разными типами столбцов - ожидаемое поведение?

Каково ожидаемое поведение из-за SQL Standard, когда мы выполняем UNION для двух таблиц с разными типами данных:

create table "tab1" ("c1" varchar(max));
create table "tab2" ("c3" integer);
insert into tab1 values(N'asd'), (N'qweqwe');
insert into tab2 values(123), (345);
select
c_newname as myname
from
(
select "c1" as c_newname from "tab1"
union all
select "c3" from "tab2"
) as T_UNI;

MS SQL Server дает

Ошибка преобразования при преобразовании значения varchar asd в тип данных int.

а что определено в стандарте?


person alex    schedule 05.05.2015    source источник
comment
не уверен, откуда взялась tab3, но вы не можете объединить два разных типа данных. Это то, что говорит вам SQL Server.   -  person Christian Barron    schedule 05.05.2015
comment
@ChristianBarron Спасибо, tab3 должен быть tab1, извините. Я понимаю, что говорит мне SQL Server, мне интересно, что говорит стандарт SQL по этому вопросу.   -  person alex    schedule 05.05.2015


Ответы (3)


Если вы хотите использовать столбцы union all в каждом запросе, они должны иметь один и тот же тип. C3 необходимо преобразовать в varchar, потому что c1 — это varchar. Попробуйте решение ниже

create table "tab1" ("c1" varchar(max));
create table "tab2" ("c3" integer);
insert into tab1 values(N'asd'), (N'qweqwe');
insert into tab2 values(123), (345);
select
c_newname as myname
from
(
select "c1" as c_newname from "tab1"
union all
select cast("c3"  as varchar(max)) from "tab2"
) as T_UNI;

Я заменил "tab3" на "tab1" - думаю, опечатка.

person Robert    schedule 05.05.2015
comment
Спасибо за ваши усилия - я знаю о возможности исправить запрос таким образом, но мне все еще интересно, что ожидает стандарт SQL. - person alex; 05.05.2015
comment
@alex Как я уже сказал выше. Типы столбцов в каждом запросе должны совпадать. Если 1-й столбец имеет значение int, каждый запрос должен возвращать значение int. - person Robert; 05.05.2015

Со страницы T-SQL UNION:

Ниже приведены основные правила объединения наборов результатов двух запросов с помощью UNION:

  • Количество и порядок столбцов должны быть одинаковыми во всех запросах.
  • Типы данных должны быть совместимы.

Когда один тип данных имеет значение VARCHAR, а другой — INTEGER, SQL Server неявно попытается преобразовать VARCHAR в INTEGER (правила описаны в таблице приоритетов). Если преобразование не удается для какой-либо строки, запрос завершается ошибкой. Итак, это работает:

INSERT INTO #tab1 VALUES(N'123'), (N'345');
INSERT INTO #tab2 VALUES(123), (345);
SELECT C1 FROM #tab1 UNION ALL SELECT C2 FROM #tab2

Но это не так:

INSERT INTO #tab1 VALUES(N'ABC'), (N'345');
INSERT INTO #tab2 VALUES(123), (345);
SELECT C1 FROM #tab1 UNION ALL SELECT C2 FROM #tab2
-- Conversion failed when converting the varchar value 'ABC' to data type int.

Правила конвертации описаны здесь:

Приоритет типов данных T-SQL


Сказав это, вы можете явно преобразовать ваши целочисленные данные в varchar, чтобы заставить запрос работать (тип данных результата будет varchar).

person Salman A    schedule 05.05.2015
comment
круто, спасибо за ссылку на приоритет типов данных, я этого не знал. - person alex; 05.05.2015

Основное правило таково: Либо используемый тип данных должен быть одинаковым в двух таблицах(или) вы должны использовать функцию приведения или преобразования для соответствия типам данных в этих двух таблицах.

Стандарт SQL:

1)Количество и порядок столбцов должны быть одинаковыми во всех запросах.
2)Типы данных столбцов должны быть совместимыми: они не обязательно должны быть одного и того же типа, но они должны относиться к типу, который может поддерживать SQL Server. неявно преобразовать.

person Hell Boy    schedule 05.05.2015