1

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

我们使用 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.

4

2 回答 2

2

尝试

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

扩展一点——当你通过 DBi 接口传递一个本地浮点/双精度时,它被转换为一个字符串,如果你没有另外指定,它使用 Perl 的默认格式约定(由 C 编译器强加)。默认值为 6 位精度,如果数字超过该数字,则以科学计数法呈现。

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

于 2009-09-24T18:15:49.430 回答
0

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

于 2009-09-25T05:04:13.153 回答