仰天一笑(Ansonxuyu),专业从事软件定制开发、Web软件开发,网站建设,网络推广,APP开发,微博应用开发,微信应用开发,电子商务开发,物联网开发等技术。
互联网8年风雨,愿在此交朋识友,交流心得,分享技术知识(策划/研发/运营/推广/合作)!QQ:943530498


仰天一笑

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

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

      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  仰天一笑  阅读(5965)  评论(14编辑  收藏  举报