UNION ALL 两个具有不同列类型的 SELECTs - 预期行为?

ale*_*lex 6 sql t-sql sql-server standards union-all

当我们UNION对具有不同数据类型的两个表执行时,由于 SQL Standard 的预期行为是什么:

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;
Run Code Online (Sandbox Code Playgroud)

MS SQL Server

将 varchar 值“asd”转换为数据类型 int 时转换失败。

但是标准中定义了什么?

Sal*_*n A 8

T-SQL UNION页面:

以下是使用 UNION 组合两个查询的结果集的基本规则:

  • 在所有查询中,列的数量和顺序必须相同。
  • 数据类型必须兼容。

当一种数据类型是VARCHAR,另一种是INTEGERSQL Server 将隐式尝试转换VARCHARINTEGER(规则在优先级表中描述)。如果任何行的转换失败,则查询失败。所以这有效:

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

但这不会:

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.
Run Code Online (Sandbox Code Playgroud)

此处描述了转换规则:

T-SQL 数据类型优先级


话虽如此,您可以显式地将整数数据转换为 varchar 以使查询工作(结果的数据类型将是 varchar)。


Rob*_*ert 6

如果要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;
Run Code Online (Sandbox Code Playgroud)

我替换"tab3""tab1"- 我认为这是错字。