PHP stmt 准备失败但没有错误

PHP stmt prepare fails but there are no errors

我正在尝试准备一个 mysqli 查询,但它无提示地失败了,没有给出任何错误。

 $db_hostname  = "test.com";
 $db_database   = "dbname";
 $db_username  = "db_user";
 $db_password   = "password";
 $db = new mysqli($db_hostname,$db_username,$db_password,$db_database);

 $q = "INSERT INTO Members (`wp_users_ID`,`MemberID`,`Status`,`MiddleName`,`Nickname`,`Prefix`,`Suffix`,`HomeAddress`,`City`,`State`,`Zip`,`ExtendedZip`,`BadAddress`,`SpouseFirstName`,`SpouseMiddleName`,`HomePhone`,`CellPhone`,`WorkPhone`,`WorkPhoneExt`,`OfficePhone`,`OfficePhoneExt`,`Pager`,`Fax`,`Company`,`CompanyType`,`OfficeAddress`,`OfficeAddress2`,`OfficeCity`,`OfficeState`,`OfficeZip`,`OTYPECO`,`OSTAG`,`UPCODE`,`Region`,`Department`,`Classification`,`Retired`,`Industry`,`Comments`,`Officer`,`OfficerType`,`OfficerTitle`,`OUNIT`,`ReceiveEMagazine`,`CD`,`SD`,`AD`,`isOrganization`,`DEL`,`Dues`,`DataSource`) VALUES ((?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?));";
 $stmt = $db->prepare($q);
 if ( false === $stmt ) {
      echo "<pre>";
      print_r( $db );
      echo "</pre>";
      mysqli_report(MYSQLI_REPORT_ALL);
      echo mysqli_error();
      }

唯一真正显示任何内容的部分是 print_r( $db ):

 mysqli Object
 (
      [affected_rows] => -1
      [client_info] => 5.1.73
      [client_version] => 50173
      [connect_errno] => 0
      [connect_error] => 
      [errno] => 0
      [error] => 
      [error_list] => Array
      (
      )
      [field_count] => 1
      [host_info] => dbhost.com via TCP/IP
      [info] => 
      [insert_id] => 919910
      [server_info] => 5.1.73-log
      [server_version] => 50173
      [stat] => Uptime: 1924325  Threads: 8  Questions: 642600129  Slow queries: 28158  Opens: 24168750  Flush tables: 1  Open tables: 403  Queries per second avg: 333.935
      [sqlstate] => 00000
      [protocol_version] => 10
      [thread_id] => 9939810
      [warning_count] => 0
 )

有人看到会导致这种情况的原因吗?没有任何错误,很难看出哪里出了问题...我尝试将生成的查询直接复制并粘贴到 phpmyadmin 中,它 运行 就好了(在用测试值手动替换问号之后)。

谢谢!

更新

似乎自从将 mysqli_report(MYSQLI_REPORT_ALL); 添加到页面顶部后,插入查询上方的查询现在失败了,虽然仍然没有给出错误。这个执行失败:

 echo "1";
 $idDataSources = "";
 echo "2";
 $q = "SELECT idDataSources FROM DataSources WHERE `description`=(?);";
 echo "3";
 $stmt = $db->prepare($q);
 echo "4";
 $stmt->bind_param('s',$description);
 echo "5";
 $description = "File - 01/10/2015";
 echo "6";
 $stmt->execute() or die( mysqli_stmt_error( $stmt ) );
 echo "7";
 $stmt->bind_result($idDataSources);
 echo "8";
 $stmt->fetch();
 echo "9";
 unset($params);

输出:

 123456

它到达 $stmt->execute() 并失败。我再次尝试输出错误,但没有任何显示。这真是莫名其妙。我想知道我是否应该恢复到旧的 mysql(非面向对象)方法......它不安全,但至少它始终如一地工作并在出现问题时显示错误。

更新 2

好吧,我只是使用 mysql(非面向对象)而不是 mysqli 重写了整个脚本……就像做梦一样。我希望我可以切换到更新的标准,但是由于存在 运行dom 故障和像这样糟糕的错误报告,这确实很困难。我会搁置 "better" 版本,直到我弄清楚它失败的原因。

更新 3

我注意到 mysqli 有一个有趣的行为。在同一代码的其他地方,我通过 STMT 有两个查询 运行 一个接一个。这每隔一段时间就会失败。失败并不一致,因为我可以提交相同的数据 50 次,其中可能会失败 20 次...相同的数据,相同的功能。

为了准确识别脚本出错的位置,我在两个查询中的每个语句之间放入了 echo 命令,只是吐出一个数字以查看计数停止的位置 - 结果是不相关的命令,它减慢了 STMT 的速度,足以使其始终如一地工作。这让我怀疑 STMT 连接是否未正确关闭。

$q = "";
$stmt = $this->db->prepare( "SELECT ID FROM Members WHERE MemberID='5' LIMIT 1;" );
$stmt->execute();
$stmt->store_result();
if ( $stmt->num_rows > 0 ) {
    $q = "UPDATE Members SET Name='Test' WHERE MemberID=(?) LIMIT 1;";
    }
$stmt->close();

// here if we continue, it has a chance of erroring out. However, 
// if we run just the following command instead, everything works perfect.
//  
// mysql_query( "UPDATE Members SET Name='Test' WHERE MemberID='5' LIMIT 1;" );

if ( $q != "" ) {
    $stmt = $this->db->prepare($q);
    $stmt->bind_param('i',$params['ID']);
    $params['ID'] = 5;
    $stmt->execute();
    $stmt->close();
    unset($params);
    }

任何人都可以解释这种行为吗?它们似乎不应该发生冲突,因为我在开始新查询之前使用了 close() 命令,而且它在某些时候确实有效……看起来很奇怪。

这是来自 php.net 的带有错误处理的稍微改编的示例脚本:

<?php
$mysqli = new mysqli("example.com", "user", "password", "database");
if ($mysqli->connect_errno) {
   echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

/* Prepared statement, stage 1: prepare */
if (!($stmt = $mysqli->prepare("SELECT idDataSources FROM DataSources WHERE `description`=(?)"))) {
     echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

/* Prepared statement, stage 2: bind and execute */
$description = "File - 01/10/2015";
if (!$stmt->bind_param('s', $description)) {
    echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}

if (!$stmt->execute()) {
    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}

/* explicit close recommended */
$stmt->close();
?>

请注意 $mysqli $stmt 都可以保存错误描述。

在你的初始 post;

$q = "INSERT INTO Members (`wp_users_ID`,`MemberID`,`Status`,`MiddleName`,`Nickname`,`Prefix`,`Suffix`,`HomeAddress`,`City`,`State`,`Zip`,`ExtendedZip`,`BadAddress`,`SpouseFirstName`,`SpouseMiddleName`,`HomePhone`,`CellPhone`,`WorkPhone`,`WorkPhoneExt`,`OfficePhone`,`OfficePhoneExt`,`Pager`,`Fax`,`Company`,`CompanyType`,`OfficeAddress`,`OfficeAddress2`,`OfficeCity`,`OfficeState`,`OfficeZip`,`OTYPECO`,`OSTAG`,`UPCODE`,`Region`,`Department`,`Classification`,`Retired`,`Industry`,`Comments`,`Officer`,`OfficerType`,`OfficerTitle`,`OUNIT`,`ReceiveEMagazine`,`CD`,`SD`,`AD`,`isOrganization`,`DEL`,`Dues`,`DataSource`) VALUES ((?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?),(?));";

我会把它改成;

$q = "INSERT INTO Members (`wp_users_ID`,`MemberID`,`Status`,`MiddleName`,`Nickname`,`Prefix`,`Suffix`,`HomeAddress`,`City`,`State`,`Zip`,`ExtendedZip`,`BadAddress`,`SpouseFirstName`,`SpouseMiddleName`,`HomePhone`,`CellPhone`,`WorkPhone`,`WorkPhoneExt`,`OfficePhone`,`OfficePhoneExt`,`Pager`,`Fax`,`Company`,`CompanyType`,`OfficeAddress`,`OfficeAddress2`,`OfficeCity`,`OfficeState`,`OfficeZip`,`OTYPECO`,`OSTAG`,`UPCODE`,`Region`,`Department`,`Classification`,`Retired`,`Industry`,`Comments`,`Officer`,`OfficerType`,`OfficerTitle`,`OUNIT`,`ReceiveEMagazine`,`CD`,`SD`,`AD`,`isOrganization`,`DEL`,`Dues`,`DataSource`) VALUES (?, ?, ..., ?, ?)";

我删除了 MySQL 查询中双引号中的那个分号。我还删除了问号周围的括号。当然,值中的省略号 (...) 只是为了让我不必输入所有问号(您应该将它们放回您的代码中)。

我遇到了同样的问题。问题是我正在使用多个准备好的语句重新使用相同的 mysqli 连接。 在每个执行语句之后,我确定要包括显式关闭命令:

$stmt->close();

这阻止了错误消息被抑制,然后我可以在 $mysqli->error 中看到错误消息。