gpt4 book ai didi

mysql - perl dbi mysql - 值精度

转载 作者:太空宇宙 更新时间:2023-11-04 09:57:57 25 4
gpt4 key购买 nike

user@host:~# mysql -V - mysql Ver 14.14 Distrib 5.7.25-28, for debian-linux-gnu (x86_64) using 7.0 running under debian-9,9

user@host:~# uname -a - Linux 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19 ) x86_64 GNU/Linux

user@host:~# perl -MDBI -e 'print $DBI::VERSION ."\n";' - 1.636

user@host:~# perl -v 这是为 x86_64-linux-gnu-thread 构建的 perl 5,版本 24,subversion 1 (v5.24.1) -多

mysql> SHOW CREATE TABLE tbl1;

tbl1 | CREATE TABLE `tbl1` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `main_id` bigint(20) NOT NULL DEFAULT '0',  `debet` varchar(255) NOT NULL DEFAULT '',  `kurs` double(20,4) NOT NULL DEFAULT '0.0000',  `summ` double(20,2) NOT NULL DEFAULT '0.00',  `is_sync` int(11) NOT NULL DEFAULT '0',  PRIMARY KEY (`id`),  KEY `main_id` (`main_id`)  ) ENGINE=InnoDB AUTO_INCREMENT=70013000018275 DEFAULT CHARSET=utf8 

mysql> SELECT * FROM tbl1 WHERE id=70003020040132;

-+---------------+----------------+-------+--------+---------+---------+| id             | main_id        | debet | kurs   | summ    | is_sync | +----------------+----------------+-------+--------+---------+---------+| 70003020040132 | 70003020038511 |       | 0.0000 | 1798.00 | 0       |+----------------+----------------+-------+--------+---------+---------+

But when I get this data by perl::DBI module I lose precisions, and values 0.0000 and 1798.00 becomes 0 and 1798.

Code is next:

#### 
#These 3 subs are connecting to DB, executing query and get data by fetchall_arrayref and coverting undef to NULL.
####
sub DB_connect {
# DataBase Handler
my $dbh = DBI->connect("DBI:mysql:$DBNAME", $DBUSER, $DBPWD,{RaiseError => 0, PrintError => 0, mysql_enable_utf8 => 1}) or die "Error connecting to database: $DBI::errstr";
return $dbh;
}
sub DB_executeQuery {
# Executes SQL query. Return reference to array, or array, according to argv[0]
# argv[0] - "A" returns array, "R" - reference to array
# argv[1] - DB handler from DB_connect
# argv[2] - query to execute

my $choice=shift @_;
my $dbh=shift @_;
my $query=shift @_;
print "$query\n" if $DEBUG>2;
my $sth=$dbh->prepare($query) or die "Error preparing $query for execution: $DBI::errstr";
$sth->execute;
my $retval = $sth->fetchall_arrayref;

if ($choice eq "A" ) {
my @ret_arr=();
foreach my $value (@{ $retval }) {
push @ret_arr,@{ $value };
}
return @ret_arr;
}
elsif ($choice eq "R") {
return $retval;
}
}

sub undef2null {
# argv[1] - reference ro array of values where undef
# values has to be changed to NULL
# Returns array of prepared values: (...) (...) ...
my $ref=shift @_;
my @array=();
foreach my $row (@{ $ref }) {
my $str="";
foreach my $val ( @{ $row} ) {
if (! defined ( $val )) {
$str="$str, NULL";
}
else {
# Escape quotes and other symbols listed in square brackets
$val =~ s/([\"\'])/\\$1/g;
$str="$str, \'$val\'";
}
}
# Remove ', ' at the beginning of each VALUES substring
$str=substr($str,2);
push @array,"($str)";
} # End foreach my $row (@{ $ref_values })
return @array;
} # End undef2null

#### Main call
#...
# Somewhere in code I get data from DB and print it to out file
my @arr_values=();
my @arr_col_names=DB_executeQuery("A",$dbh,qq(SELECT column_name FROM `information_schema`.`columns` WHERE `table_schema` = '$DBNAME' AND `table_name` = '@{ $table }'));
@arr_ids=DB_executeQuery("A",$dbh,qq(SELECT `id` FROM `@{ $table }` WHERE `is_sync`=0));
my $ref_values=DB_executeQuery("R",$dbh,"SELECT * FROM \`@{ $table }\` WHERE \`id\` IN(".join(",",@arr_ids).")");
@arr_values=undef2null($ref_values);
print FOUT "REPLACE INTO \`@{ $table }\` (`".join("`, `",@arr_col_names)."`) VALUES ".(join ", ",@arr_values).";\n";

结果我得到下一个字符串:

REPLACE INTO `pko_plat` (`id`, `main_id`, `debet`, `kurs`, `summ`, `is_sync`) VALUES  ('70003020040132', '70003020038511', '', '0', '1798', '0')

在 DB 中它是 0.0000 - 变成 0,是 1798.00,变成 1798

Perl 的 DBI 文档说它“按原样”将数据获取到字符串中,不进行任何翻译。但是,那么,谁对值进行四舍五入?

最佳答案

您看到的舍入是由于您创建列的方式造成的。

  `kurs` double(20,4) NOT NULL DEFAULT '0.0000'
`summ` double(20,2) NOT NULL DEFAULT '0.00'

如果您查看 mysql floating point type documentation您会发现您使用的是非标准语法 double(m, d),其中两个参数定义了 float 的输出方式。

因此,在您的情况下,存储在 summ 中的值将在小数点后显示 2 位数字。这意味着当 perl 从数据库中的表中获取 1.0001 的值时,perl 获取的数据库传递的值将四舍五入到设置的位数(在本例中为 .00)。

Perl 依次将此值(“1.00”)解释为 float ,并且在打印时不会显示任何尾随零。如果你想要这些,你应该在你的输出中考虑到这一点。

例如:print sprintf("%.2f\n", $summ);

在我看来,您可以采用两种方式(如果您想避免这种精度损失):

  • 仅将具有正确精度的数字添加到数据库中(因此对于 'summ',只有两个尾随数字,对于 'kurs',只有四个尾随数字。)
  • 将您的表创建更改为 float 的标准语法并确定 Perl 中的输出格式(您将以任何一种方式进行):
`kurs` double() NOT NULL DEFAULT '0.0'

关于mysql - perl dbi mysql - 值精度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58640607/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com