【发布时间】:2020-08-26 08:47:24
【问题描述】:
我开发了一个 Perl 脚本,可以将数据格式化为 CSV 格式,并希望将数据保存到 Postgres 数据库表中。
我是following this tutorial,作为如何与 Postgres 交互的指南。我在 PPM 中验证了我安装了与教程相同的版本:1.634 版本的 DBI 和 3.5.3 版本的 DBD::Pg 安装在 Windows 10 x64 的 Perl 5.22.1 中。该数据库是 Windows Server 2008r2 上的 Postgres 12。
Perl 脚本的第一部分读取、解析一条数据记录并将其格式化为 CSV。 这是一个 CSV 数据记录的示例:
"2020-05-10 20:39:16+0","0.528239011764526","15:39 05/10/2020","0x1c","LOW STATUS","0x85","Normal","73.8","32","29.11","29.31","61.2","29","80","0.7","2.5","22.6","378.64","3009","7","0.00","0.00","0.97","0.97","11.96"
这是在进入下面的数据库界面sn -p之前存储在$SQLstring中的: 这是我从教程中修改的代码,它编译并运行没有错误。
# ------------- Postgres Database Connection --------------
# Connection config
my $dbname = 'MyDatabase';
my $host = '192.168.1.1';
my $port = 5432;
my $username = 'myuser';
my $password = 'mypassword';
# Create DB handle object by connecting
my $dbh = DBI -> connect("dbi:Pg:dbname=$dbname;host=$host;port=$port",
$username,
$password,
{AutoCommit => 0, RaiseError => 1}
) or die $DBI::errstr;
# Trace to a file
$dbh -> trace(1, 'tracelog.txt');
# Copy from STDIN into the table
my $SQL = "COPY AmbientWeather (
datetimestamp ,
CurrTime ,
IndoorID ,
inBattSta ,
Outdoor1ID ,
outBattSta1 ,
inTemp ,
inHumi ,
AbsPress ,
RelPress ,
outTemp ,
outHumi ,
windir ,
avgwind ,
gustspeed ,
dailygust ,
solarrad ,
uv ,
uvi ,
rainofhourly ,
rainofdaily ,
rainofweekly ,
rainofmonthly ,
rainofyearly
)
FROM STDIN WITH DELIMITER ',' CSV HEADER";
my $sth = $dbh->do($SQL);
# putcopy data from saved line in CSV format
$dbh->pg_putcopydata($SQLstring);
$dbh->pg_putcopyend(); # finished with one line
$dbh->commit or die $DBI::errstr;
exit;
这运行没有错误,但数据库没有改变。不创建记录。
这是跟踪日志,没有显示任何明显的错误,但我对语法不是很熟悉:
DBI::db=HASH(0x3c62268) trace level set to 0x0/1 (DBI @ 0x0/0) in DBI 1.634-ithread (pid 19436)
<- DESTROY(DBI::db=HASH(0x3c62268))= ( undef ) [1 items] at Ambient_Parser.pl line 158
DBI::db=HASH(0x3c76ca8) trace level set to 0x0/1 (DBI @ 0x0/0) in DBI 1.634-ithread (pid 2108)
<- do('COPY AmbientWeather (
datetimestamp ,
CurrTime ,
IndoorID ,
inBattSta ,
Outdoor1ID ,
outBattSta1 ,
inTemp ,
inHumi ,
AbsPress ,
RelPress ,
outTemp ,
outHumi ,
windir ,
avgwind ,
gustspeed ,
dailygust ,
solarrad ,
uv ,
uvi ,
rainofhourly ,
rainofdaily ,
rainofweekly ,
rainofmonthly ,
rainofyearly
...')= ( -1 ) [1 items] at Ambient_Parser.pl line 177
<- pg_putcopydata('"2020-05-10 20:35:59+0","0.547099113464355","15:35 05/10/2020","0x1c","LOW STATUS","0x85","Normal","73.6","32","29.11","29.31","61.3","24","193","3.8","4.9","22.6","380.54","3082","7","0.00","0.00","0.97","0.97","11.96"
')= ( 1 ) [1 items] at Ambient_Parser.pl line 182
<- pg_putcopyend= ( 1 ) [1 items] at Ambient_Parser.pl line 183
<- commit= ( 1 ) [1 items] at Ambient_Parser.pl line 184
<- DESTROY(DBI::db=HASH(0x3c76ca8))= ( undef ) [1 items] at Ambient_Parser.pl line 193
参考第193行是最后的出口;在文件中。
我一定遗漏了什么,但我不知道它是什么。你能指出我的错误吗?
编辑:我将 $SQL = "COPY.... 中的教程命令中的选项与 Postgres COPY command documentation 进行了比较。教程添加了选项 CSV HEADER,这在 Postres 文档中没有看到。我不知道为什么这些选项在教程中使用,或者为什么它们会导致静默失败。我删除了它们,现在出现错误。
上面的代码现在看起来像这样:
rainofyearly
)
FROM STDIN WITH DELIMITER ','";
现在正在输出这些错误:
DBD::Pg::db pg_putcopyend failed: ERROR: invalid input syntax for type real: ""0.520319223403931""
CONTEXT: COPY ambientweather, line 1, column fetchelapsed: ""0.520319223403931"" at Ambient_Parser.pl line 186.
DBD::Pg::db pg_putcopyend failed: ERROR: invalid input syntax for type real: ""0.520319223403931""
CONTEXT: COPY ambientweather, line 1, column fetchelapsed: ""0.520319223403931"" at Ambient_Parser.pl line 186.
Issuing rollback() due to DESTROY without explicit disconnect() of DBD::Pg::db handle dbname=MyDatabase;host=192.168.1.1;port=5432 at Ambient_Parser.pl line 186.
我正在调查为什么真正的价值被视为双引号。这与我在 PSQL 命令行中使用 COPY FROM 使用的 CSV 格式相同,并且如上所示接受了实数。
【问题讨论】:
-
我的猜测是,
invalid input syntax for type real: "0.520319223403931"你需要一个数字,但你将它作为参数传递给双引号。 -
@GeorgMavridis 如果他在第二次尝试中没有放弃 CSV 选项,那么引号就不会成为问题。指定 DELIMITER ',' 但不指定 CSV 意味着引号只是文字字符,与数字类型不兼容。
标签: postgresql perl dbi