仰天一笑

昨日不悔,今日勿失,明日莫忧! —徐羽

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  241 随笔 :: 27 文章 :: 876 评论 :: 43 引用

      SQLServer有很强的格式自动转换功能,但是他不是万能的,有些时候也是转换不了的,而且出现错误我们很难查找,因为我们有些时候是可以的,有些时候又出现问题。正确之时都是SQLServer格式转换范围内的,那些超出界限的,就会出现错误,而出现错误的时候,我们的程序员就会陷入一个误区:检查别的地方代码,而且为此浪费很多的时间,贻误了工程进度,对项目来说是有害的,对自己来说,更是有害的。下面有个例子,我们可以参考一下,借此说明此问题。

问题陈述:
有一天,执行
SELECT * FROM XXX_ORIGINAL_20031205
where msgid=62010388000012

语句,结果SQL Server报告出错:“将数据类型 varchar 转换为 numeric 时出错。”

这是什么意思呢?

Msgid这个字段的类型是:varchar(30)。

原因分析:
不是SQL Server突然不能从数字自动转换为字符串,而是单单对这个字段的数值有问题,这也和这个字段中实际已存储的字符串有关。

你看,我执行这个SQL语句是没有问题,可以自动转换:

SELECT * FROM XXXX_ORIGINAL_20031205
where recordid=62010388000012

recordid这个字段的类型也是:varchar(30)。
这为什么就可以呢?

为什么?

这是因为msgid字段的真实数值是类似于这样的字符串“12051113280101053509”,由于你的SQL命令中要求拿字符串跟我们提供的这个数字62010388000012匹配,所以SQLServer默认要把这么多个“12051113280101053509”先统统转换为数字,再去跟62010388000012匹配。

(首先这就涉及到一个效率问题,转换这么多msgid成为数字,再跟你的数字匹配,将是一个多么大的浪费啊)

当然,这回SQLServer转不过来了,因为“12051113280101053509”换为数字实在太大了,超出了范围,所以你看SQLServer于是乎报告“将数据类型 varchar 转换为 numeric 时出错”,他指的就是把历史数据“12051113280101053509”这个varchar(30)转成numeric不行,而不是把你SQL脚本传递的参数62010388000012转换失败。

让我们看看另一种形式的错误,就更清楚了:

我们执行

SELECT * FROM XXXX_ORIGINAL_20031205
where msgid=120

命令就会得到错误:

varchar 值 '12050003010101026986' 的转换溢出了 int 列。超出了最大整数值。

这个错误,是不是很清楚地表明了SQLServer在帮你执行SQL命令时背后所作的事情?

他试图帮你主动把记录中的这个字段转换成你在SQL命令中指明的那个数据类型。

总结:

很多时候,我们懒得去看某个字段到底是什么类型,是char,还是tinyint,还是bool,还是varchar,我们就随便写一个数字,让聪明的SQL Server自己去判断该转成什么。

再次我将聪明的SQL Server自动转换给我们带来的害处简单罗列:

1、增加出错次数,而且出现错误容易让我们陷入误区,让我们的程序不够健壮。
2、自动转换会增加SQL的执行时间,让我们的程序没有效率。
3、给我们程序带来无限隐患,为后期的功能延伸带来麻烦


建议:

不积硅步何以至千里,千里长堤溃于蚁穴。希望程序员兄弟们以次为鉴,自己勤快一点,养成一个好的习惯,在错误产生之前搞定他。请自己判断好格式,然后将数据传给SQLServer,因为相信机器,不如相信自己。

posted on 2007-03-05 11:19 仰天一笑 阅读(3198) 评论(14)  编辑 收藏 网摘 所属分类: DataBase

评论

#1楼 2007-03-05 11:21 Artech      
建议用摘要的形式发布。
  回复  引用  查看    

#2楼 2007-03-05 11:40 补丁      
不良习惯带来问题
  回复  引用  查看    

#3楼[楼主] 2007-03-05 12:16 仰天一笑      
@补丁
一语中的

  回复  引用  查看    

#4楼 2007-03-05 12:42 JesseZhao      

  回复  引用  查看    

还有人写SQL不看字段类型,太懒了 :P
  回复  引用    

没有给出解决方案?
  回复  引用    

#7楼 2007-03-05 14:04 Bention      
原来是这样问题啊,难怪俺以前经常碰到此类的问题呢,我还是喜欢匹配着类型去写
  回复  引用  查看    

#8楼[楼主] 2007-03-05 15:13 仰天一笑      
@风海迷沙
希望程序员兄弟们以次为鉴,自己勤快一点,养成一个好的习惯,在错误产生之前搞定他。请自己判断好格式,然后将数据传给SQLServer,因为相信机器,不如相信自己,哈哈。

  回复  引用  查看    

不错!
  回复  引用    

#10楼 2007-03-05 17:21 Anders Liu      
@风海迷沙
拜托,是字符型的都用''括起来....

  回复  引用  查看    

#11楼 2007-03-05 20:29 丁丁      
Sign, SQL Server竟然有这个功能?怎么把它关闭?
  回复  引用  查看    

#12楼 2007-03-05 22:02 Kai.Ma[匿名]
用存储过程不就行了吗?
  回复  引用    

#13楼 2007-03-06 17:25 耶耶[未注册用户]


NET交流群(上海站):36840133

  回复  引用    

#14楼 2007-05-26 10:31 elite[未注册用户]
好啊
但是出了错以后,有没有解决办法?

  回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 664031




相关文章:

相关链接: