当我在 SQL Server 中尝试此即席查询时(假设
UserId
是 NVARCHAR 字段):
SELECT * FROM MyUser WHERE UserId = 123456
我收到此错误:
消息 245,第 16 级,状态 1,第 1 行 将 nvarchar 值“foo”转换为数据类型 int 的列时出现语法错误。
显然在我的
'foo'
列下有一个值UserId
。
为什么 SQL Server 尝试将我的整个列转换为 INTEGER,而不是执行对我来说显而易见的操作:将我的搜索值转换为 NVARCHAR?
使用数据类型优先级的规则进行比较:
当操作员将两个 不同数据类型的表达式, 数据类型优先级规则 指定数据类型 较低的优先级被转换为 优先级较高的数据类型。
优先级1表示最高。因此
NVARCHAR
类型(优先级 25)转换为 int
(优先级 16),因为 NVARCHAR
在此规模中的优先级较低。
我认为这是因为它无法比较不同类型的两个值。然后,必须将两个相等比较成员转换为相同类型。我想,在这里,
int
是首选。
我相信
int
优先于 nvarchar
类型,因此它必须隐式尝试将 nvarchar
转换为 int 值。
编辑#1
“但是,尝试将我给出的值转换为我正在搜索的字段的类型,而不是相反,这不是明智的做法吗?”
是的,如果可以的话那就太好了。但我想这是因为在尝试其他类型的比较时会有太多的转换尝试暗示。
where dateOfBirth = 1976-6-16
对
where dateOfBirth = N'1976-06-16'
在第一个例子中,用户的意图是什么?是验证
dateOfBirth
是否等于1976-06-16
的日期值,还是与1976 - 6 - 16
的整数值进行比较,得到1954
,这可以合理地认为它是年份任何给定的日期。
我认为存在隐式转换,例如
nvarchar
到 datetime
,但有很多内容需要涵盖,因此他们将自己限制为最常见的可能转换。
如果您知道列是 NVARCHAR,为什么还要指定整数值?
不幸的是,与许多 SQL 实现一样,SQL Server 在类型支持方面远远落后于其他语言。类型检查通常仅在运行时执行。因此,像您这样的查询不会进行语法检查以突出显示您在这里遇到的问题。您的查询有问题,因为您不匹配不同的类型,但由于 SQL Server 不会对其进行验证,因此结果将是不可预测的,具体取决于数据。