如果对遇到以下错误的其他任何人有所帮助,请告诉我:
SQLState: 24000 [Microsoft][ODBC SQL Server Driver]Invalid cursor state
PDOStatement :: closeCursor() 无法解决我的问题。但是,在存储过程的开头添加 SET NOCOUNT ON 确实可以解决问题。
(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.9.0)
PDOStatement::closeCursor — 关闭游标,使语句能够再次执行
PDOStatement::closeCursor() 释放与服务器的连接,以便可以发出其他 SQL 语句,但会将语句保留在能够再次执行的状态。
此方法对于不支持执行先前执行的 PDOStatement 对象仍有未获取行的 PDOStatement 对象的数据库驱动程序很有用。如果您的数据库驱动程序存在此限制,则问题可能会在执行顺序错误中表现出来。
PDOStatement::closeCursor() 作为可选的驱动程序特定方法实现(实现最高效率),或者如果未安装驱动程序特定函数,则作为通用的 PDO 备用实现。PDO 通用备用语义上等同于在您的 PHP 脚本中编写以下代码:
<?php
do {
while ($stmt->fetch())
;
if (!$stmt->nextRowset())
break;
} while (true);
?>
此函数没有参数。
如果属性 PDO::ATTR_ERRMODE
设置为 PDO::ERRMODE_WARNING
,则会发出级别为 E_WARNING
的错误。
如果属性 PDO::ATTR_ERRMODE
设置为 PDO::ERRMODE_EXCEPTION
,则会抛出 PDOException。
示例 #1 PDOStatement::closeCursor() 示例
在以下示例中,$stmt PDOStatement 对象返回多行,但应用程序仅获取第一行,将 PDOStatement 对象保留在具有未获取行的状态。为了确保应用程序能够与所有数据库驱动程序一起使用,作者在执行 $otherStmt PDOStatement 对象之前,在 $stmt 上插入对 PDOStatement::closeCursor() 的调用。
<?php
/* 创建 PDOStatement 对象 */
$stmt = $dbh->prepare('SELECT foo FROM bar');
/* 创建第二个 PDOStatement 对象 */
$otherStmt = $dbh->prepare('SELECT foobaz FROM foobar');
/* 执行第一个语句 */
$stmt->execute();
/* 从结果中仅获取第一行 */
$stmt->fetch();
/* 以下对 closeCursor() 的调用可能被某些驱动程序需要 */
$stmt->closeCursor();
/* 现在我们可以执行第二个语句 */
$otherStmt->execute();
?>
如果对遇到以下错误的其他任何人有所帮助,请告诉我:
SQLState: 24000 [Microsoft][ODBC SQL Server Driver]Invalid cursor state
PDOStatement :: closeCursor() 无法解决我的问题。但是,在存储过程的开头添加 SET NOCOUNT ON 确实可以解决问题。
如果您运行的是 SQL 语句(而不是返回数据的查询),例如 UPDATE,请尝试取消设置 PDOStatement 对象,而不是调用 PDOStatement::closeCursor()。
当在一个接一个地运行多个查询时,尤其是在涉及存储过程的情况下,必须在转到下一个查询之前释放所有结果集并在每个结果集中获取所有行(对于存储过程而言)。这很重要,因为存储过程在调用过程本身时会返回一个额外的(空的)结果集。
在我的情况下,调用 PDOStatement :: closeCursor() 无法正常工作(在 php-5.1.3-rc2 上),并且在尝试 PDO :: prepare() 我的第二个查询时遇到了以下错误消息:“SQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query”。因此,我在我的一个类中使用了以下替换,解决了问题。
<?php
/**
* @param PDOStatement $oStm
*/
public static function closeCursor($oStm) {
do $oStm->fetchAll();
while ($oStm->nextRowSet());
}
?>