[英]How can I tell DBD::CSV to use a comma as the decimal seperator?
I'm trying to use a German-style CSV file with DBI and DBD::CSV . 我正在尝试使用带有DBI和DBD :: CSV的德式CSV文件。 This, in turn, uses Text::CSV to parse the file.
反过来,这使用Text :: CSV来解析文件。 I want to query the data in that file using SQL.
我想使用SQL查询该文件中的数据。
Let's look at the file first. 我们先来看一下这个文件。 It is separated by semicolons (
;
), and the numbers in it look like this: 5,23
, which is equivalent to the English 5.23
. 它用分号(
;
)分隔,其中的数字如下: 5,23
,相当于英文5.23
。
Here's what I've got so far: 这是我到目前为止所得到的:
use strict; use warnings;
use DBI;
# create the database handle
my $dbh = DBI->connect(
'dbi:CSV:',
undef, undef,
{
f_dir => '.',
f_schema => undef,
f_ext => '.csv',
f_encoding => 'latin-1',
csv_eol => "\n",
csv_sep_char => ';',
csv_tables => {
foo => {
file => 'foo.csv',
#skip_first_row => 0,
col_names => [ map { "col$_" } (1..3) ], # see annotation below
},
},
},
) or croak $DBI::errstr;
my $sth = $dbh->prepare(
'SELECT col3 FROM foo WHERE col3 > 80.50 ORDER BY col3 ASC'
);
$sth->execute;
while (my $res = $sth->fetchrow_hashref) {
say $res->{col3};
}
Now, this looks quite nice. 现在,这看起来很不错。 The problem is that the SQL (meaning SQL::Statement, which is somewhere down the line from DBI and DBD::CSV) does not regard the data in
col3
, which is a floating-point value with a comma in the middle, as a float. 问题是SQL(意思是SQL :: Statement,它位于DBI和DBD :: CSV的某个位置)不考虑
col3
的数据, col3
是一个浮点值,中间有一个逗号,如一个浮子。 Instead, it treats the column as an integer, because it doesn't understand the comma. 相反,它将列视为整数,因为它不理解逗号。
Here's some example data: 这是一些示例数据:
foo;foo;81,90
bar;bar;80,50
baz;baz;80,70
So the above code with this data will result in one line of output: 81,90
. 所以带有这些数据的上述代码将产生一行输出:
81,90
。 Of course, that is wrong. 当然,这是错误的。 It used the
int()
part of col3
with the comparison, which is right, but not what I want. 它使用
col3
的int()
部分进行比较,这是对的,但不是我想要的。
Question: How can I tell it to treat the numbers with the comma as float? 问题: 如何告诉它用逗号处理数字为浮点数?
Things I've thought about: 我想过的事情:
Changing the source CSV file to have dots instead of commas is not an option. 不能选择将源CSV文件更改为带点而不是逗号。
I'm open for all kinds of suggestions. 我愿意接受各种建议。 Other approaches to the whole CSV via SQL thing are welcome, too.
通过SQL的其他方法也很受欢迎。 Thanks a lot.
非常感谢。
You need to write a user-defined function using SQL::Statement::Functions
(already loaded as part of DBD::CSV
). 您需要使用
SQL::Statement::Functions
(已作为DBD::CSV
一部分加载)编写用户定义的函数。
This program does what you want. 这个程序做你想要的。 Adding
0.0
to the transformed string is strictly unnecessary, but it makes the point about the purpose of the subroutine. 在变换后的字符串中添加
0.0
是完全没必要的,但它说明了子程序的用途。 (Note also your typo in the f_encoding
parameter to the connect
call.) (另请注意
connect
调用的f_encoding
参数中的拼写错误。)
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect(
'dbi:CSV:',
undef, undef,
{
f_dir => '.',
f_schema => undef,
f_ext => '.csv',
f_encoding => 'latin-1',
csv_eol => "\n",
csv_sep_char => ';',
csv_tables => {
foo => {
file => 'test.csv',
#skip_first_row => 0,
col_names => [ map { "col$_" } (1..3) ], # see annotation below
},
},
},
) or croak $DBI::errstr;
$dbh->do('CREATE FUNCTION comma_float EXTERNAL');
sub comma_float {
my ($self, $sth, $n) = @_;
$n =~ tr/,/./;
return $n + 0.0;
}
my $sth = $dbh->prepare(
'SELECT col3 FROM foo WHERE comma_float(col3) > 80.50 ORDER BY col3 ASC'
);
$sth->execute;
while (my $res = $sth->fetchrow_hashref) {
say $res->{col3};
}
output 产量
80,70
81,90
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.