【问题标题】:Why am I getting 'Error converting data type varchar to numeric' on a floating point number in Perl?为什么在 Perl 中的浮点数上出现“将数据类型 varchar 转换为数字时出错”?
【发布时间】:2010-12-01 04:35:00
【问题描述】:

我们从 Perl 将值插入到类型为 NUMERIC(19,5) 的 SQL Server 2005 数据库列中。只要绝对值是 0.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.

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      试试

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

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

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

      【讨论】:

      • 我必须记住强制浮点数正确格式化,而不是正确处理 Perl 的自动浮点格式,这似乎很不方便。
      • 是的,但是必须在某些时候决定转换为科学记数法,他们只是选择使用编译器的默认值。有关更多信息,请参阅perldoc.perl.org/perlnumber.html
      • C 库的默认值,而不是编译器的。
      • 更多的是我认为 DBI 应该处理识别它仍然是一个数字,而不是尝试将其作为字符串发送到 SQL 服务器,而不是反对科学计数法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      相关资源
      最近更新 更多