使用perl时使用存储在变量中的mysql查询时会发生绑定参数错误?

时间:2016-11-10 05:16:50

标签: mysql perl

我附上了以下代码,但我遇到了以下错误。任何人都可以解决问题的原因吗?

$DBH1->do("USE data_current;");
$stm1="select * from data_1m.wms  where time =(select max(time) from wms)";
$stmt2="insert into data_current.wms(time,available,closed,used,busy,reserved,down) values(select * from data_1m.wms  where time =(select max(time) from wms)";
my $sth1 = $DBH1->prepare( "$stmt1" );  
$sth1->execute($stmt2) or print "Could not insert data";            
$sth1->finish;
$DBH1->disconnect();

发生以下错误:

  

DBD :: mysql :: st执行失败:当0为0时,使用1个绑定变量调用   需要

2 个答案:

答案 0 :(得分:3)

我担心我对one of my comments yesterday感到困惑。这就是我所说的:

  

看起来这与你的Perl无关。您的SQL返回了错误的数据(出于我不理解的原因)。这是做什么的。在源数据库上打开mysql会话。编写一个返回正确数据的SQL语句。将insert into ...子句添加到该SQL的前面。从Perl执行该SQL

我试图解开这里的误解。但是,考虑到我们在这个看似简单的任务上回答了多长时间,我想知道你是否有时间放弃并聘请程序员来为你做这件事。

此任务分为两个阶段。首先,您需要识别一个选择您感兴趣的数据的SQL语句。其次,您需要将select语句转换为insert into ...语句并从Perl程序中执行该语句。

对于第一阶段,您根本不需要Perl。您只需要一个连接到源数据库的mysql命令行程序。然后,您可以尝试一些SQL语句,直到找到一个可以提供所需数据的语句。看起来你认为你需要的陈述是:

select *
from   data_1m.wms
where  time = (select max(time) from wms)

太棒了。我可能会对SQL进行两次调整。我明确列出了我选择的列,并且我指定了wms表所在的数据库。所以它看起来像这样:

select time, available, closed, used, busy, reserved, down
from   data_1m.wms
where  time = (select max(time) from data_1m.wms)

现在我们需要将其转换为insert ...语句。这可能看起来像这样:

insert into data_current.wms(time,available,closed,used,busy,reserved,down)
select time, available, closed, used, busy, reserved, down
from   data_1m.wms
where  time = (select max(time) from data_1m.wms)

(与您的情况略有不同 - 您在values声明中不需要insert ... select ...关键字。)

这就是你需要从你的Perl程序运行的东西。实际上,您可以先从mysql命令行程序对其进行测试,以确保它能做正确的事情。

现在我们来解决你当前的问题。这就是我开始认为你可能最好还是让别人为你做这件事的原因 - 因为这个问题是由于你根本没有阅读(或不理解)DBI的基础知识引起的。

在DBI中运行查询是一个两阶段的过程。您prepare()查询并返回一个语句句柄。然后,在该语句句柄上调用execute()以实际执行查询。在文档中没有任何地方甚至暗示您可以在现有语句句柄上将另一个(新)语句传递给execute()方法。如果要运行另一个语句,则需要prepare()该语句获取新的语句句柄,然后在该语句句柄上运行execute()

(允许将参数传递给execute(),以便定义插入到SQL中的"绑定点"中的值。这就是您遇到错误的原因。但是你没有使用绑定点。)

因此,要在代码中执行您想要执行的操作,您可以编写如下代码:

my $stm1="select * from data_1m.wms  where time =(select max(time) from wms)";
my $stmt2="insert into data_current.wms(time,available,closed,used,busy,reserved,down) values(select * from data_1m.wms  where time =(select max(time) from wms)";
my $sth1 = $DBH1->prepare( $stmt1 );
$sth1->execute() or print "Could not insert data";            
$sth1->finish;
my $sth2 = $DBH1->prepare( $stmt2 );
$sth2->execute;
$sth2->finish;
$DBH1->disconnect();

但是(我希望我已经在上面说明了)你不需要这样做,因为$stmt1是完全没必要的。另外(as Chankey points out)使用insert ...方法运行do()语句比prepare() / execute()周期更容易。

如果昨天我的评论让你困惑,我道歉。我真的试图尽可能清楚。但我真的认为在继续解决这个问题之前你需要退后一步并深呼吸。通过随机改变事物开始看起来有点像你在编程 - 这绝不是一个好方法。

答案 1 :(得分:1)

非SELECT语句的典型方法调用序列是:

prepare,
  execute,
  execute,
  execute

现在您正在尝试将数据插入到表中,这是非SELECT语句。所以你应该遵循同样的方法。

1)准备声明

my $sth = $dbh->prepare("INSERT INTO...");

2)执行准备好的陈述

$sth->execute(); #pass @bind_values if there are any

或者您也可以使用do()方法。

$rows_affected = $dbh->do("INSERT INTO ...");

请仔细阅读documentation of DBI了解详情。

  

DBD :: mysql :: st执行失败:当需要0时使用1个绑定变量调用

您收到上述错误是因为您正在将另一个语句传递给execute方法,而execute方法只接受绑定值,在您的情况下不是。