2010-11-19 42 views
1

当我尝试在SQL Server此即席查询(假设UserId是NVARCHAR场):SQL Server隐式类型转换在这种情况下如何工作?

SELECT * FROM MyUser WHERE UserId = 123456 

我得到这个错误:

 
Msg 245, Level 16, State 1, Line 1 
Syntax error converting the nvarchar value 'foo' to a column of data type int. 

显然有一个价值'foo'某处我UserId列。

为什么SQL Server试图将我的整个列转换为INTEGER,而不是做我认为显而易见的事情:将我的搜索值转换为NVARCHAR?

+0

我不知道它为什么这样做。但这就是它总是这样:) – 2010-11-19 16:52:13

回答

3

的比较是使用的Data Type Precedence规则进行:

When an operator combines two expressions of different data types, the rules for data type precedence specify that the data type with the lower precedence is converted to the data type with the higher precedence.

NVARCHAR类型(优先级25)转化为int(优先级16)。请注意,优先级1表示“最高”。

+0

+1这正是我试图用我自己的话来解释的东西。感谢这个伟大的链接! =) – 2010-11-19 17:03:14

+0

我认为这是查询优化器在将查询传递到引擎之前应该能够处理的事情:将我的搜索值转换为可以工作的类型,发出警告并让我脱身。呃,好吧。 :-) – Tomalak 2010-11-19 17:03:42

+0

@Tomalak:也许在未来的SQL Server版本中! = P Hehehe ... – 2010-11-19 17:05:12

2

我认为这是因为它无法比较不同类型的两个值。然后,必须将等式比较成员转换为相同类型。在这里,我猜,int是首选。

我认为int优先于nvarchar类型,所以它必须隐式尝试将nvarchar转换为int值。

编辑#1

"But wouldn't it be sensible to try and convert the value I have given to the type of the field I am searching in, instead of the other way around?"

是的,如果它这样做就好了。但我想这是因为尝试其他类型的比较时尝试暗示会有太多转化。

where dateOfBirth = 1976-6-16 

VS

where dateOfBirth = N'1976-06-16' 

在第一个例子,什么是用户的意图?是否要验证dateOfBirth是否等于日期值1976-06-16或与整数值1976 - 6 - 16比较,这将导致1954,这可能是合理的,足以将其视为任何给定日期的年份。

我认为有隐含的转换,例如nvarchardatetime,但是要覆盖很多,所以它们限制了最常见的转换。

+0

但是,尝试将我给定的值转换为我正在搜索的字段的类型而不是相反的方法是否明智? – Tomalak 2010-11-19 16:53:07

+1

是的。这很烦人,因为它似乎故意避免使用索引 - 即使您已获得用户标识的主键并查找表中的主键,您仍然可以找到结果,但您也可以点击错误(也就是说,你会得到一个结果行,作为与不匹配行不同的错误).Oracle也这样做了,我从来没有看到过它的意义。我想这只是默认类型升级/转换规则的副作用。 – 2010-11-19 16:57:33

+0

'where dateOfBirth = 1976-6-16'的意思显然是'1976 - 6 - 16'的算术结果。 DATETIME是一个数字类型,用户给了一个数字输入(一个表达式,但不过)。如果我给它一个字符串('N'1976-06-16''),服务器*显然会在使用它之前将它转换为DATETIME,否则这些查询将不起作用。所以它实际上可以足够聪明,在我的问题中描述的情况下做同样的事情。 ;-)但我很欣赏事情是这样的。 – Tomalak 2010-11-19 17:12:23

1

如果您知道列是NVARCHAR,为什么要指定整数值?

不幸的是,与许多SQL实现一样,SQL Server与类型支持中的其他语言相比还有很长的路要走。类型检查通常只在运行时执行。所以像你这样的查询没有语法检查,以突出像你在这里的问题。您的查询存在错误,因为您的数据类型不匹配,但由于SQL Server未对其进行验证,所以结果将不可预知,具体取决于数据。

+0

为什么?因为这是一个临时查询,我没有想到这次输入引号。我对这个错误信息的巨大愚蠢感到惊讶,并想知道它背后是否有更深的理由。原来,没有 - 它“就是这样”。 – Tomalak 2010-11-19 17:39:20

+0

@Tomalak:一个更好的错误信息将是“类型不匹配” - 但解决方案仍然是相同的:修复您的查询以指定正确的值类型。 – sqlvogel 2010-11-19 17:41:29

+0

我不是故意说*消息的措辞很愚蠢,我说的是SQL Server *处理这种情况的方式很愚蠢。 ;-) – Tomalak 2010-11-19 19:00:09

相关问题