为什么 Varchar 的数据类型优先级低于 INT?

SEa*_*986 2 sql-server datatypes errors implicit-conversions

给出下表:

CREATE TABLE #a
(
    MyInt INT
)

INSERT INTO #a VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)

CREATE TABLE #b
(
    MyVarchar VARCHAR(10)
)

INSERT INTO #b VALUES('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('ten')
Run Code Online (Sandbox Code Playgroud)

如果我运行以下查询;

SELECT  *
FROM    #a
        LEFT JOIN #b
            ON #a.MyInt = #b.MyVarchar
Run Code Online (Sandbox Code Playgroud)

SQL Server 必须执行隐式转换,因为#a.MyInt#b.MyVarchar是不匹配的数据类型。由于数据类型优先级,具有最低类型优先级 (#b.MyVarchar) 的列将转换为较高优先级 (INT) 的类型

这意味着上面的查询等效于

SELECT  *
FROM    #a
        LEFT JOIN #b
            ON #a.MyInt = CONVERT(INT,#b.MyVarchar)
Run Code Online (Sandbox Code Playgroud)

两者都失败,因为其中某个值#b.MyVarchar对于列来说是无效值INT

我的问题是为什么 的VARCHAR优先级低于INT?如果是相反的情况,隐式转换将会成功,但我们会得到一个错误的查询。为什么错误比成功执行更可取?我的猜测是,这对于 SQL Server 来说更像是一种“防御”机制 - 它更喜欢错误,因此需要用户明确决定他们想要做什么,而不是在用户不知情的情况下给出可能意外的查询结果。意识到?

Dav*_*oft 8

由于 SQL Server 是 RDBMS,因此它们针对针对正确定义的表发送 SQL 查询的应用程序进行了优化。

降低 varchar 的数据类型优先级使引擎能够在评估将参数作为文字字符串或 varchar 参数发送的查询时避免对列表达式进行隐式转换:

select * 
from someTable
where SomeIntColumn = '1'
Run Code Online (Sandbox Code Playgroud)

或者

where SomeDateColumn = '2024-01-01'
Run Code Online (Sandbox Code Playgroud)

在这两种常见情况下,我们避免转换每一行的值并使用此策略启用索引查找。

这也使得查询的形式

where SomeIntColumn = 'not convertable to int'
Run Code Online (Sandbox Code Playgroud)

失败而不是返回零行。