为什么 Perl DBI 接口无法插入到 Postgres table?
Why does Perl DBI interface fail to INSERT to Postgres table?
我开发了一个可以将数据格式化为 CSV 格式的 Perl 脚本,想将数据保存到 Postgres 数据库中 table。
我 following this tutorial 作为如何与 Postgres 交互的指南。我在 PPM 中验证我安装了与教程相同的版本:DBI 的 1.634 版本和 DBD::Pg 的 3.5.3 版本安装在 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"
在进入下面的数据库界面片段之前,它存储在 $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;
这运行没有错误,但数据库没有改变。没有创建记录。
这是跟踪日志,没有显示任何table错误,但我不太熟悉语法:
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 格式相同,并且如上所示接受了实数。
你告诉它第一行将被忽略 header。但是你只发送了一行。所以没有发送数据线。
CSV 和 HEADER 是单独的选项。这些都(单独)存在于您 link 的文档中。需要保留CSV,否则引号看不懂
我开发了一个可以将数据格式化为 CSV 格式的 Perl 脚本,想将数据保存到 Postgres 数据库中 table。
我 following this tutorial 作为如何与 Postgres 交互的指南。我在 PPM 中验证我安装了与教程相同的版本:DBI 的 1.634 版本和 DBD::Pg 的 3.5.3 版本安装在 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"
在进入下面的数据库界面片段之前,它存储在 $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;
这运行没有错误,但数据库没有改变。没有创建记录。
这是跟踪日志,没有显示任何table错误,但我不太熟悉语法:
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 格式相同,并且如上所示接受了实数。
你告诉它第一行将被忽略 header。但是你只发送了一行。所以没有发送数据线。
CSV 和 HEADER 是单独的选项。这些都(单独)存在于您 link 的文档中。需要保留CSV,否则引号看不懂