【问题标题】:Bind parameter error occurs when using mysql queries stored in variables using perl?使用perl存储在变量中的mysql查询时发生绑定参数错误?
【发布时间】:2017-03-24 01:21:03
【问题描述】:

我附上了以下代码,但遇到以下错误。谁能解决问题的原因?

$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 时使用 1 个绑定变量调用 需要

【问题讨论】:

  • $sth1->execute($stmt2) 为什么要将 $stmt2 作为参数传递给 $stmt1?
  • 我想执行 $stmt2 查询所以我传递为 $stmt2@e4c5
  • 花 30 秒阅读准备和执行文档很简单
  • 顺便说一句:你设置了变量$stm1,然后在prepare()调用中使用$stmt1

标签: mysql perl


【解决方案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 方法只接受绑定值,在您的情况下不接受。

【讨论】:

    【解决方案2】:

    恐怕我把你和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)
    

    (这与您所拥有的略有不同 - 您不需要在 insert ... select ... 语句中使用 values 关键字。)

    这就是您需要从 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) 使用 do() 方法运行 insert ... 语句比使用 prepare()/execute() 循环要容易得多。

    如果昨天我的 cmets 让您感到困惑,我深表歉意。我真的试图尽可能清楚。但我真的认为你需要退后一步,深呼吸几次,然后再继续解决这个问题。它开始看起来有点像您在通过随机更改事物进行编程 - 这绝不是一个好方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 2016-03-29
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多