奇怪的SQL Server类型转换问题

时间:2011-08-01 09:11:31

标签: sql-server-2005 tsql .net-2.0

我今天遇到了奇怪的问题。我的一个项目是运行.NET + SQL Server 2005 Express。 我使用一个查询进行一些过滤。

SELECT *
  FROM [myTable]
  where UI = 2011040773395012950010370
GO

SELECT *
  FROM [myTable]
  where UI = '2011040773395012950010370'
GO

UI列为nvarchar(256),传递给过滤器的UI值始终为25位。

在我的DEV环境中 - 两个查询都返回相同的行而没有错误。但是在我的客户中,经过几个月的正常运行后,第一个版本开始返回类型转换错误。

知道为什么吗?

我不是在寻找解决方案 - 我正在寻找解释为什么在一个环境中它起作用而在另一个环境中却没有,为什么突然之间它开始返回错误而不是结果。我在两者上使用相同的工具(SQL Server Management Studio Express和2个不同的.NET客户端)

环境或多或少相同(W2k3 + SQL Server 2005 Express)

1 个答案:

答案 0 :(得分:5)

由于Datatype precedence

,这是完全可预测和预期的

为此,UI列将更改为十进制(25,0)

where UI = 2011040773395012950010370

这个几乎是正确的。右侧是varchar,更改为nvarchar

where UI = '2011040773395012950010370'

这是真正正确的版本,其中两种类型相同

where UI = N'2011040773395012950010370'

错误已经开始,因为UI列现在包含一个不会CAST到十进制(25,0)的值。

一些不相关的说明:

  • 如果您在UI列上有索引,则由于需要隐式CAST,它将在第一个版本中被忽略
  • 你需要unicode来存储数字吗?存储和性能中有serious overhead个unicode数据类型
  • 为什么不使用char(25)nchar(25)值是固定长度?您使用too much memory as the optimiser的查询假设平均长度为128个字符,基于nvarchar(256)

评论后编辑

不知道它确实有效时,不要假设“为什么它有时会起作用”

示例:

  • 该值可能已删除,稍后再添加
  • TOP子句或SET ROWCOUNT可能意味着未达到违规值
  • 查询从未运行,因此无法失败
  • 其他一些代码会忽略该错误?

编辑2希望更清晰

<强>聊天

GBN:

  

运行WHERE UI = 2011040773395012950010370时,您不知道行访问的顺序。因此,如果一行确实有“自行车”,您可能会或可能不会碰到该行。

随机:

  

所以问题可能不是我试图访问的行,而是其他一个值已损坏的行?

GBN

  

根据服务包级别,索引和表碎片,CPU数量,并行性,不同的机器将具有不同的读取顺序

     

正确

     

和TOP甚至。那种东西

正如陶提到,重要的是要明白另一个不相关的人可以打破查询,即使这个是好的。

  

数据类型优先级可导致在评估where子句之前转换该列中的所有数据