为什么不要让 SQLServer 帮你自动转换 SQL 命令中的数据类型
** Report Date ** ** : ** ** ** 2003/12/5
|
** Prepared by ** ** : ** ** ** 郑 昀
---|---
Article last modified on 2004-2-16 ** **
The information in this article applies to:
ü Microsoft SQL Server 2000,7.0
问题陈述 :
有一天,执行
SELECT * FROM XXX_ORIGINAL_20031205
where ** msgid ** =62010388000012
语句,结果 SQL Server 报告出错: “ 将数据类型 varchar 转换为 numeric 时出错。 ”
这是什么意思呢?
Msgid 这个字段的类型是: varchar(30) 。
** 环境: ** ** **
数据库服务器: Microsoft SQL Server 2000 以及 7.0 ;
数据库服务器补丁: Microsoft SQL Server 2000 ServicePack1 ;
原因分析:
不是 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 不是转换你的脚本命令中的数值,而是转换已有的历史数据到你指定的那个类型,所以会增加执行时间;第二,容易转换出错。
所以,切忌让 SQLServer 自己判断,自动帮你转换,那样将降低执行效率,而且增加出错几率。你能够显式告诉 SQL Server 你的数据类型的话,就请一定这么做。
Writen by zhengyun.NoJunk(at)tomosoft.dot.com
Disclaimers :
本文档所包含的信息代表了在发布之日, ZhengYun 对所讨论问题的当前看法, Zhengyun 不保证所给信息在发布之日以后的准确性。
本文档仅供参考。对本文档中的信息, Zhengyun 不做任何明示或默示的保证。
用户必须遵守所有适用的版权法。在不对版权法所规定的权利加以限制的情况下,如未得到 **_ zhengyun _ ** 和 **_ CSDN.Net _ ** 明确的书面许可,不得出于任何目的、以任何形式或手段(电子的、机械的、影印、录制等等)复制、传播本文的任何部分,也不得将其存储或引入到检索系统中。