【问题标题】:PHP PDO fails on every write operationPHP PDO 在每次写入操作时都会失败
【发布时间】:2011-06-30 20:47:18
【问题描述】:

所有 SELECT 都能正常工作。但是,任何 UPDATE 或 INSERT,即使它在 mysql 查询浏览器中执行时有效,同时使用与 PHP 连接到服务器相同的用户登录,但在 PDO 执行时会失败。

举个例子:

SELECT *  FROM Projects WHERE ssdUserID = :ssdUserID;

始终正常工作,而

INSERT INTO Projects SET ssdUserID = :ssdUserID, json = :json;

从 PHP 执行时总是失败,尽管我在所有参数上都做了 addlashes()。

我调用 PDO 的方式是通过准备好的语句:

$connection = new PDO("mysql:host=$mysqlServer;
    dbname=$mysqlSchema", $mysqlUser, $mysqlPassword);;
$statement = $connection->prepare($sql);
$result = $statement->execute($parameters);

$result 始终为 false,尽管最后发生了提交(暂时出于调试目的),但在数据库中看不到更新或插入。

我启用了 mysql 跟踪日志,似乎 sql 甚至没有发送到 mysql 服务器 - 在跟踪日志中可以看到的只是事务的开始和结束,中间没有任何内容。

由于搜索工作,很明显 PDO 能够建立与数据库的连接。此外,由于搜索使用的代码与不适用于 write 语句的代码相同,因此除了 PDO 本身之外,我想不出任何其他地方有问题。

一个可能很重要的问题是上面示例中的 json 列是文本类型。我已经在另一个地方使用过 PDO,我只有各种 VARCHAR 列,并且在那里它可以正常工作。

有没有人遇到过类似的问题?有人可以帮我解决这个问题吗?


更新:

经过一些挖掘和阅读 (http://www.php.net/manual/en/pdo.lobs.php),我切换到了不同的解决方案。我现在绑定输入参数和输出列。不过,我会保留最初的文本,所以犯同样的最初错误的人可能会比我更容易发现。

绑定参数很容易。我将输出列绑定在一个通用函数中:

01  private function __extractResultsEx($statement, $columns)
02  {
03      $data = array();
04      $msg = "query returned ".$statement->rowCount()." rows";
05      $receiverRow = array();
06      $i = 1;
07      foreach ($columns as $column => $type)
08      {
09          $receiverRow[$column] = NULL;
10          $statement->bindColumn($i++, &$receiverRow[$column], $type);
11      }
12      while ($statement->fetch(PDO::FETCH_BOUND))
13      {
14          $row = array();
15          foreach ($columns as $column => $type)
16              $row[$column] = $receiverRow[$column];
17          $data[] = $row;
18      }
19      return $data;
20  }

列是 ID/PDO::PARAM_INT、userID/PDO::PARAM_INT 和 json/PDO::PARAM_LOB。

我不知道是否需要第 09 行,只是在最初尝试 $receiverRow 最后确实有三个元素但没有初始化之后,我认为这可能会有所帮助 - 但它没有。

使用这种方法,问题是尽管在第 04 行 $statement 说它已经检索到一行,但执行永远不会到达 while 循环内部(第 14 - 17 行),因为 $statement-fetch() 总是返回 false,no无论我使用哪个 PDO::FETCH_ 常量(我尝试了 PDO::FETCH_OBJ、PDO::FETCH_BOUND 和 PDO::FETCH_ASSOC,另一个似乎对 LOB 没有多大意义,无论如何手册页只提到了 PDO: :FETCH_BOUND 用于 LOB)。

上面提到的手册页的 cmets 中记录了一个错误,它说从行中读取 LOB 应该是安全且可以的。尽管如此,我什至在访问行数据之前就出现了问题,尽管我似乎已经按照示例代码中的方式完成了所有操作。

不过,现在有一项改进。 mySQL 跟踪显示我正在执行的 SQL。此外,由于第 04 行提到了我期望的行,我想我已经接近解决方案了 - 但我似乎无法确定它。

【问题讨论】:

  • 您当时是否还有另一个打开的连接,可能是您尚未关闭的读取查询?
  • 能不能也贴一下绑定参数的代码?

标签: php mysql pdo


【解决方案1】:

你有多个问题:

确保$parameters 是这样的数组:

array('ssdUserID' => "val", 'json' => "{}");

另外,在使用准备好的语句时,您不需要调用addslashes。 PDO 会为您做到这一点。

要查找错误,您可以添加以下内容(在您的 $statement->execute() 调用之后):

var_dump($connection->errorInfo());

PS:new PDO(... 行中的分号过多。

【讨论】:

  • 他原来的INSERT也可以用,mysql允许这种语法
  • "真正的问题是你的 SQL 语法不正确。"不,这不对。 INSERT INTO table SET column = value 是完全合法的 MySQL 语法。请参阅:dev.mysql.com/doc/refman/5.0/en/insert.html,第二个示例。
  • 哦。奇怪的。我以前从未见过。也许 PDO 也认为这是不正确的?我会相应地更新我的答案。
  • 检查准备调用是否也成功。如果失败,那么执行肯定会失败,但你错过了检索错误信息的机会。
  • 如果准备失败,则执行调用将失败并出现致命错误,因为方法 execute 不会存在于非对象 false 上。
【解决方案2】:

您可以尝试调用bindParam 而不是将参数传递给execute 吗? 您可能需要为 text 类型的列指定长度。

$statement->bindParam(':ssdUserID',$user_id, PDO::PARAM_INT);
$statement->bindParam(':json',$json_str,  PDO::PARAM_STR,strlen($json_str) );
$result = $statement->execute();

【讨论】:

  • 这样做了。现在我有以下函数来提取结果 - 在 $statement->execute() 之后调用:
猜你喜欢
  • 2012-05-15
  • 2015-05-30
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多