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 时转换失败。
但是标准中定义了什么?
从T-SQL UNION页面:
以下是使用 UNION 组合两个查询的结果集的基本规则:
- 在所有查询中,列的数量和顺序必须相同。
- 数据类型必须兼容。
当一种数据类型是VARCHAR,另一种是INTEGERSQL 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
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)
此处描述了转换规则:
话虽如此,您可以显式地将整数数据转换为 varchar 以使查询工作(结果的数据类型将是 varchar)。
如果要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"- 我认为这是错字。