【问题标题】:Failed or success query always return true失败或成功查询总是返回 true
【发布时间】:2015-05-11 14:42:50
【问题描述】:

代码:

$new_deb = 5;
//prepare query();
$q = 'START TRANSACTION;';
for($l = 0; $l < $cond; $l++){
    if($uploaded == 0 || $uploaded == "0"){
        $q .= ' INSERT INTO vocher (`vo_type_id`, `account_id`, `value`, `desc`, `user_id`, `status_id`, `date`, `debtor_id`)';
        $q .= ' VALUES ("'.$vouchertype.'", "'.$voucheracc[$l].'","'.$vdebvalue[$l].'", "'.$vdebdesc[$l].'","'.$_POST['usrSes'].'", "'.$status.'","'.$vocherdate[$l].'", "'.$new_deb.'");';
    }else{
        $q .= ' INSERT INTO vocher (`vo_type_id`, `account_id`, `value`, `desc`, `user_id`, `status_id`, `date`, `debtor_id`, `link`)';
        $q .= ' VALUES ("'.$vouchertype.'", "'.$voucheracc[$l].'","'.$vdebvalue[$l].'", "'.$vdebdesc[$l].'","'.$_POST['usrSes'].'", "'.$status.'","'.$vocherdate[$l].'", "'.$new_deb.'", "'.$newAttach.'");';
    }

    $q .= ' SET @lastId = (SELECT `id` FROM vocher ORDER BY `id` DESC LIMIT 1);';
    if($voCc[$l] != 'e'){
        for($h = 0; $h < count($voCc[$l]); $h++){
            if($voCc[$l][$h] != 'e'){
                $q .= ' INSERT INTO voucher_cc (`voucher`, `cc`) VALUES (@lastId, "'.$voCc[$l][$h].'");';
            }
        }
    }

    if(in_array($voucheracc[$l], $inResetAccs)){
        $q .= ' INSERT INTO resets ( `type`, `acc`, `user`, `value`, `desc`, `debtor_id`, `date`, `status`)';
        $q .= ' VALUES ("IN", "'.$voucheracc[$l].'", "'.$_POST['usrSes'].'", "'.$vdebvalue[$l].'", "'.$vdebdesc[$l].'", "'.$new_deb.'", "'.$vocherdate[$l].'", "1");';
    }
}

for($z = 0; $z < $chqradiolength; $z++){
    if ($chqradio[$z] == "0") {
        $q .= ' INSERT INTO creditor (`acc_id`, `value`, `bank_id`, `debtor_id`, `cheque_no`, `issue_date`, `available_date`, `vo_type_id`, `desc`, `date`, `user`)';
        $q .= ' VALUES ("'.$chequeAcc[$z].'", "'.$vvalue[$z].'", "'.$banks[$z].'", "'.$new_deb.'", "'.$vsn[$z].'", "'.$issuesdates[$z].'", "'.$availabledate[$z].'", "'.$vouchertype.'", "'.$vdesc[$z].'", "'.$credates[$z].'", "'.$_POST['usrSes'].'");';
        $q .= ' SET @creLastId = (SELECT `id` FROM creditor ORDER BY `id` DESC LIMIT 1);';
        for($x = 0; $x < count($chequeCc[$z]); $x++){
            $q .= ' INSERT INTO creditor_cc (`creditor`, `cc`) VALUES (@creLastId, "'.$chequeCc[$z][$x].'");';
        }
    }else{
        $q .= ' INSERT INTO creditor (`acc_id`, `value`, `debtor_id`, `date`, `desc`, `vo_type_id`, `user`)';
        $q .= ' VALUES ("'.$creaccs[$z].'", "'.$vvalue[$z].'", "'.$new_deb.'" , "'.$credates[$z].'" , "'.$vdesc[$z].'" , "'.$vouchertype.'", "'.$_POST['usrSes'].'");';
        $q .= ' SET @creLastId = (SELECT `id` FROM creditor ORDER BY `id` DESC LIMIT 1);';

        if($creCc[$z] != 'e'){
            for($x = 0; $x < count($creCc[$z]); $x++){
                if($creCc[$z][$x] != 'e'){
                    $q .= ' INSERT INTO creditor_cc (`creditor`, `cc`) VALUES (@creLastId, "'.$creCc[$z][$x].'");';
                }
            }
        }

        if(in_array($creaccs[$z], $outResetAccs)){
            $q .= ' INSERT INTO resets (`type`, `acc`, `user`, `value`, `desc`, `debtor_id`, `date`, `status`)';
            $q .= ' VALUES ("OUT", "'.$creaccs[$z].'" , "'.$_POST['usrSes'].'" , "'.$vvalue[$z].'", "'.$vdesc[$z].'" , "'.$new_deb.'", "'.$credates[$z].'", "1");';
        }
    }
}
$q .= ' COMMIT;';
$vocher_obj->query($q);
$check = $vocher_obj->execute();
if($check){
    $res = 1;
}else{
    $res = 23;
}

echo $res;

此代码用于生成一些查询。

即使我将表名更改为数据库中的“不存在”表,这些查询也总是返回“true”,而它应该返回“false”!

你能帮我解决这个问题吗?

【问题讨论】:

  • 您不应该将多个查询语句填充到单个查询调用中。而且您的代码本质上是活泼的。您不应该使用select ... 来获取最后生成的ID。有insert_id()。不能保证其他人不会在你背后插入记录。
  • 这就是为什么我要创建一个事务,所以在事务完成之前没有其他人可以插入。而且我使用的是 PDO 而不是 MYSQLI
  • 确保您的事务设置实际上在重复读取模式下工作,然后...
  • 您正在使用 PDO,但您的 SQL 对注入开放...
  • @MarcB,我怎么能确定呢?

标签: php mysql boolean


【解决方案1】:

可能是这个bug引起的:https://bugs.php.net/bug.php?id=61613

它说,如果 FIRST 语句有效,pdo 将不会返回错误。 START TRANSACTION; 始终有效。

据报道,该错误在 PHP 5.6.7 版本之前未修复

不确定这个错误是否也会影响 return 语句,因为它与丢失异常抛出有关。但应该很容易测试:在其他任何内容之前添加一个无效语句,然后查看返回值是否为 false。

对于与 pdo 的交易,您应该查看

$pdo->beginTransaction();
$pdo->commit();
$pdo->rollback();

为避免上述错误,请将您的查询填充到一个数组中,然后像这样(简化)运行它们:

function runQueries($pdo, $queries){
  try{
    $pdo->beginTransaction();
    foreach($queries as $q){
       $pdo->exec($q);
    }
    $pdo->commit();
    return true;
  }catch (PDOException $e){
    $pdo->rollback();
    return false;
  }
}

ofc。你需要配置 PDO 来抛出 execptions,使用

$pdo = new PDO('mysql:host=localhost;dbname=someDB', 'username', 'password', array(
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));

【讨论】:

  • 我想我必须在 "$q->execute();" 之前先运行查询函数对吗?
  • @MohamedSalah 该示例在 PDOObject 上使用 exec() 而不是在 PDOStatement 上使用 execute()。适应您的需求。
  • 你能告诉我如何声明“$queries”数组吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2018-05-22
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2017-08-19
相关资源
最近更新 更多