【问题标题】:Using PDO to perform functions with a query that is based on results of another query [duplicate]使用 PDO 对基于另一个查询结果的查询执行功能 [重复]
【发布时间】:2018-03-04 04:06:34
【问题描述】:

我目前正在使用 PDO 对 MySQL 表进行选择,并让它打印结果,这在终端中是正确的。

我正在尝试对其应用“while”循环,以从 odbc 数据库中选择记录,其中第一个查询中的 order_id 等于第二个查询中的 invnoc。我认为我的问题是我如何调用order_id 并执行 DB2 部分中的语句。

如果我运行这个:

$ordStatSql = 'SELECT order_id, order_status, is_placement, date_updated 
            FROM order_status';
try{
$ordStat = $MysqlConn->prepare($ordStatSql);
$result = $ordStat->execute();
}
 catch(PDOException $ex)
{
  echo "QUERY FAILED!: " .$ex->getMessage();
 }

while($row = $ordStat->fetch(PDO::FETCH_ASSOC))

{
    echo $row['order_id'] . $row['order_status'] . $row['is_placement'] . $row['date_updated'] . "\n";

}

它运行良好,没有错误,并且打印出我预期的每一行。

但完整的脚本:

 $ordStatSql = 'SELECT order_id, order_status, is_placement, date_updated 
            FROM order_status';
try{
$ordStat = $MysqlConn->prepare($ordStatSql);
$result = $ordStat->execute();
}
 catch(PDOException $ex)
{
  echo "QUERY FAILED!: " .$ex->getMessage();
 }

while($row = $ordStat->fetch(PDO::FETCH_ASSOC))

{
    echo $row['order_id'] . $row['order_status'] . $row['is_placement'] . $row['date_updated'] . "\n";

    $detailStatCheck = '
        SELECT 
             invnoc as INVOICE,
             fstatc as STATUS,
             cstnoc AS DEALER,
             framec AS FRAME,
             covr1c AS COVER,
             colr1c AS COLOR ,
             extd2d AS SHIPDATE,
             orqtyc AS QUANTITY
        FROM GPORPCFL
        WHERE invnoc IN ?
        ORDER BY invnoc asc 
    ';

    try{
    $detailCheck = $DB2conn->prepare($detailStatCheck);
    $detailRslt = $detailCheck->execute(['order_id']);
    $count2 = $detailCheck->rowcount();
    }
    catch(PDOException $ex)
    {
        echo "QUERY FAILED!: " .$ex->getMessage();
    }
}
echo "Matches:" . $count2

它打印相同的 order_id 数字,显然需要更长的时间,但匹配显示 -1。我知道它正在拉匹配,因为我手动运行它并且它匹配每条记录。我想知道是我循环不正确还是归结为 PDO 错误。

非常感谢任何帮助。

【问题讨论】:

  • 如果您不需要 IN,请尝试使用 WHERE invnoc IN (?)'WHERE invnoc = ? 而不是 WHERE invnoc IN ?。这看起来也不对$detailCheck->execute(['order_id']);,我相信应该是$detailCheck->execute([$row['order_id']]);
  • 嗯,我做了这些更改,但我仍然得到 Matches: -1 ,但没有错误;我只是无法验证它是否匹配
  • 为了测试的目的,您可以硬编码$detailCheck->execute(['1234']);,前提是您确定此订单 ID 存在并且它总是会返回一些结果。您之前是否遇到过任何错误?
  • rowCount() 不能可靠地用于使用 ODBC 进行的SELECT 查询。尝试做SELECT COUNT(*) FROM GPORPCFL WHERE invnoc = ? ORDER BY invnoc asc 然后$count2 = $detailCheck->fetch()[0];
  • @ishegg 我在下面应用了 Bamar 的第二个解决方案,并用您的计数语法对其进行了修改,看起来它返回了正确的数字。所以它工作正常,我只是没有将它格式化为正确转储?

标签: php mysql pdo odbc


【解决方案1】:

首先,WHERE invnoc IN ? 应该是 = ?IN 用于匹配列表中的值,而不是单个值。

其次,您需要将调用中的行中的值提供给execute()

$detailRslt = $detailCheck->execute($row['order_id']);

第三,使用ORDER BY invnoc 没有意义,因为您只是匹配一个invnoc 值。

第四,每次循环都会覆盖$count2 变量。你应该在循环之前将它初始化为0,然后递增它,这样你就得到了总数:

$count2 += $detailCheck->rowCount();

您也不需要在每次循环中都准备查询。查询不会改变,所以你可以在循环之前准备一次,然后在循环中执行。

另一种选择是将所有order_id 值收集到一个数组中,并准备一个查询,将它们与IN 一次性匹配。

$order_ids = [];
while ($row = $ordStat->fetch(PDO::FETCH_ASSOC)) {
    $order_ids[] = $row['order_id'];
}
if (count($order_ids) > 0) {
    $placeholders = implode(',', array_fill(0, count($order_ids), '?'));
    $detailStatCheck = "
        SELECT 
             invnoc as INVOICE,
             fstatc as STATUS,
             cstnoc AS DEALER,
             framec AS FRAME,
             covr1c AS COVER,
             colr1c AS COLOR ,
             extd2d AS SHIPDATE,
             orqtyc AS QUANTITY
        FROM GPORPCFL
        WHERE invnoc IN ($placeholders)
        ORDER BY invnoc asc 
    ";
    try {
        $detailCheck = $DB2conn->prepare($detailStatCheck);
        $detailRslt = $detailCheck->execute($order_ids);
        $count2 = $detailCheck->rowCount();
        echo "Matches: $count2";
    } catch(PDOException $ex) {
        echo "QUERY FAILED!: " .$ex->getMessage();
    }
}

【讨论】:

  • 谢谢!我将继续并接受,但在我完全应用一种方法或另一种方法之前:一旦我完成了这个工作,我将使用匹配项执行插入另一个表。话虽如此,您认为哪种方法最有利于在此步骤之后执行更多类似的功能?
  • 尽量减少查询的数量通常是可取的,所以第二种方法。如果要插入 DB2 中的另一个表,则可以使用 INSERT ... SELECT 而不是将插入作为单独的查询进行。
  • 我将插入到 mysql 中,但我相信它仍然会更简洁。 DB2 在那里检查订单号,如果匹配,则为每条记录提取上述信息列表并插入 mysql。我对第一个解决方案有一个错误,所以我现在正在尝试第二个
  • 好的,我已经应用了第二个解决方案,没有错误,但仍然返回匹配项:-1。现在,当我用硬编码的订单 ID 替换变量时,它表明它已匹配
  • 我不明白它怎么可能是-1。如果它不匹配它应该返回0
【解决方案2】:

您的查询工作正常(除了其他答案/cmets 所说的)。您的问题实际上是在 ODBC 数据库上的 SELECT 查询上使用 rowCount()。来自the manual

使用 odbc_num_rows() 来确定 SELECT 后可用的行数将返回 -1 与许多驱动程序。

所以如果需要计数,需要选择COUNT(*)作为字段,然后查看值:

while($row = $ordStat->fetch(PDO::FETCH_ASSOC))
{
    echo $row['order_id'] . $row['order_status'] . $row['is_placement'] . $row['date_updated'] . "\n";

    $detailStatCheck = '
        SELECT 
            COUNT(*)
        FROM GPORPCFL
        WHERE invnoc = ?
    ';

    try {
        $detailCheck = $DB2conn->prepare($detailStatCheck);
        $detailRslt = $detailCheck->execute(['order_id']);
        $count2 = $detailCheck->fetch()[0]; // <---- correct count
    }
        catch(PDOException $ex)
    {
        echo "QUERY FAILED!: " .$ex->getMessage();
    }
}

【讨论】:

  • 这么快的问题:这样,通过计数,返回正确的数字。因此,为了获取 8 列信息,我需要稍后进行插入,我可以将其更改回来,因为我确认了返回值?
  • @TomN。您可以坚持使用现有查询并计算 fetch 循环中的行数。
  • @Barmar 谢谢,这是有道理的。我可以用它来测试我的数据,而不必来回切换。当我也构建一个发票数据数组时,这会有所帮助
猜你喜欢
  • 2010-10-31
  • 1970-01-01
  • 2021-10-28
  • 2018-04-29
  • 2021-06-30
  • 2023-02-07
  • 1970-01-01
  • 2018-10-17
  • 2017-11-14
相关资源
最近更新 更多