当我们对具有不同数据类型的两个表执行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;
MS SQL Server
给出
将varchar值'asd'转换为数据类型int时转换失败。
但是标准中定义了什么?
如果你想在每个查询中使用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"
- 我认为这是错字。
来自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.
转换规则如下所述:
话虽如此,您可以显式地将整数数据转换为varchar,以使查询起作用(结果的数据类型为varchar)。
基本规则是 - >在两个表(或)中使用的数据类型应该相同,您应该使用强制转换或转换函数来匹配这两个表中的数据类型。
SQL标准:
1)所有查询中列的数量和顺序必须相同。 2)列数据类型必须兼容:它们不必是完全相同的类型,但它们必须是SQL Server可以隐式转换的类型。