意外的查询结果

时间:2013-02-24 18:57:43

标签: sql-server sql-server-2008 tsql sql-server-2012

为什么我从sql-server获得以下结果?

SELECT '' + 12 C1, CONVERT(int, '') C2,
       CASE WHEN '' = ' ' THEN 'equal' ELSE 'not equal' END C3

Sql-Server Fiddle demo

--Results
| C1 | C2 |    C3 |
-------------------
| 12 |  0 | equal |

编辑: C3已被回答。每个人都回答认为'' + 12 = 12是字符串连接,但这是一个数学运算。目前尚不清楚为什么( NOT how)''在sql-server中转换为0。

3 个答案:

答案 0 :(得分:9)

这或多或少是预期的行为。从SQL(ISO / ANSI)标准的副本:

  

两个字符串表达式的比较取决于用于比较的排序规则。当比较不等长度的值时,如果比较的核对具有NO PAD特征并且较短的值等于较长值的某个前缀,则认为较短的值小于较长的值。如果比较的排序规则具有PAD SPACE特征,则出于比较的目的, 通过连接< space>来将较短的值有效地扩展到较长的长度。右 即可。

现在,大多数DBMS都实现了字符串比较,略有不同。在SQL_Server和MySQL中,您会发现''' ''  ''   '(带有0,1,2和3个空格的字符串)都相等,没有如果它们被定义为VARCHARCHAR

在Postges中,如果它们是VARCHAR,则它们都是不相等的,但如果CHAR则相等(因此VARCHAR列中没有填充)。如果其中一个是VARCHAR和一个CHAR,那么它们被发现是相等的,所以我想填充是在比较之前完成的。

Oracle类似于Postgres,具有额外的特性,即空字符串''的行为(几乎无处不在)为NULL。因此,当您将其与具有一个或多个空格(或自身)的字符串进行比较时,结果既不是True也不是False,而是UNKNOWN。 Oracle还有一个区别,如果一个字符串定义为VARCHAR而另一个字符串定义为CHAR,则比较相当复杂。从测试开始,我假设在这种情况下只填充CHAR,直到它们(定义的数据类型)长度,然后与未填充的VARCHAR进行比较。

您可以在 SQL-Fiddle

中查看(全部4个DBMS)

答案 1 :(得分:4)

C1 - 这里发生隐式转换,空字符串转换为0.这就解释了为什么你得到12(`0 + 12)。

C2 - 将''显式转换为整数会产生0。有点画像,但这就是它的工作原理(并且可能会改变 - 据我所知这没有记录,如果有人不知道,请纠正我。)

C3 - 请参阅the answer by muhmud - 基本上在比较不同长度的字符串时,较短的字符串首先用空格填充长度的长度。

答案 2 :(得分:3)

SQL Server有一个奇怪的特性,如果比较两个字符串,并且它们长度不相等,那么它会将较短的字符串填充到较长字符串的长度,然后比较它们。填充字符是一个空格。 http://support.microsoft.com/kb/316626

C1& C2只是隐含的&将空字符串显式转换为0。