为什么我在Perl中的浮点数上得到'将数据类型varchar转换为数字'的错误?

时间:2009-09-24 18:09:51

标签: sql-server sql-server-2005 perl dbi

我们正在将值插入到Perl的NUMERIC(19,5)类型的SQL Server 2005数据库列中。只要绝对值为.0001或更高,它就可以工作。但是,当值到达第5个小数位时,Perl开始以指数格式(-9e-05而不是-0.00009)存储它们,然后我们从SQL Server获得错误“Error converting data type varchar to numeric” 。我们如何防止这种情况并使其正确插入小数值?

我们使用的是perl v5.8.5,DBI 1.56,DBD :: Sybase 1.07和SQL Server 2005.

代码大致如下,但我删除了无关的字段:

$invoice->{IL_UNITPRICE} = 0.09; # Actually comes from another database
$invoice->{IL_PRICEUNITCONV} = 0.001; # Actually comes from another database
$unitprice = $invoice->{IL_UNITPRICE} * -1 * $invoice->{IL_PRICEUNITCONV};
#$unitprice equals -9e-05 at this point.
$sth = $dbh->prepare('INSERT INTO foo ( bar ) VALUES ( ? )');
$sth->execute($unitprice);

上述行失败,错误为:DBD::Sybase::st execute failed: Server message number=8114 severity=16 state=5 line=2 server=baz text=Error converting data type varchar to numeric.

2 个答案:

答案 0 :(得分:2)

尝试

$sth->execute(sprintf("%.6f",$unitprice));

扩展一点 - 当您通过DBi接口传递本机float / double时,它会转换为字符串,如果您没有另外指定,则使用Perl的默认格式约定(由C编译器强加) 。默认值为6位精度,如果数字超过了数字,则以科学计数法表示。

要获得定点格式,您必须使用sprintf明确要求它。

答案 1 :(得分:0)

实际上我认为使用Math::Bigint及其相关的Math :: BigFloat也可以解决这个问题。每当我使用浮点数或足够大的数字时,我都会使用这些模块,因此除非我真的想控制格式化,否则我不必将sprintf扔到所有地方。