当PDO::ATTR_EMULATE_PREPARE=false时,PHP PDO失败
我有一个应用程序,其中我将一个类作为参数传递给MySQL 8,该类通过使用PDO连接实例与数据库交互 为了创建到数据库的PDO连接,我必须为PDO连接使用设置为false的选项。使用PDO连接的类在执行SELECT或INSERT语句时没有问题,但在以下语句的情况下: 使用数据库名称当PDO::ATTR_EMULATE_PREPARE=false时,PHP PDO失败,php,mysql,pdo,prepared-statement,setattribute,Php,Mysql,Pdo,Prepared Statement,Setattribute,我有一个应用程序,其中我将一个类作为参数传递给MySQL 8,该类通过使用PDO连接实例与数据库交互 为了创建到数据库的PDO连接,我必须为PDO连接使用设置为false的选项。使用PDO连接的类在执行SELECT或INSERT语句时没有问题,但在以下语句的情况下: 使用数据库名称 创建触发器 下拉触发器 我收到一个错误: SQLSTATE[HY000]:一般错误:2014无法在 其他未缓冲查询处于活动状态。考虑使用 PDO语句::fetchAll()。或者,如果您的代码只是 要在mysql上运
创建触发器
下拉触发器
我收到一个错误: SQLSTATE[HY000]:一般错误:2014无法在 其他未缓冲查询处于活动状态。考虑使用 PDO语句::fetchAll()。或者,如果您的代码只是 要在mysql上运行,可以通过设置 PDO::MYSQL\u ATTR\u USE\u BUFFERED\u查询属性 但声明如下: 创建数据库
创建表格
干得好 下面是复制此问题的示例代码:
<?php
header("Content-Type: text/plain");
$user = '';
$pass = '';
$host = '';
$dbname = 'pdo_snippet';
/**
* Use at first run, the script fails at USE database-name statement
* but creates database schema $dbName
*/
$dsn = 'mysql:host=' . $host;
/**
* Use at second run, baypasses fail at USE database-name statement
* but fails at DROP TRIGGER IF EXISTS;
*/
// $dsn = 'mysql:dbname=' .$dbname. ';host=' . $host;
$options = [];
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_EXCEPTION;
$options[\PDO::ATTR_EMULATE_PREPARES] = false; # with true no problem
//---------- CONNECT TO DATABASE SERVER ---------
echo "Connect to database";
try {
$pdo = new \PDO($dsn, $user, $pass, $options);
} catch (\Exception $e) {
$msg = 'PDO could not establish connection to dsn: ' . $dsn;
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
//----------------------------------------------
//--------- CREATE SCHEMA IF NOT EXISTS --------
$sqlQuery = 'CREATE DATABASE IF NOT EXISTS `' . $dbname . '`;';
echo "Create database $dbname IF NOT EXISTS";
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
//------------------------------------------------
//----------- SELECT DEFAULT DATABASE ------------
echo "SELECT FROM default database";
$sqlQuery = "SELECT DATABASE();";
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
//------------------------------------------------
$defaultDbName = $stmt->fetchColumn();
//------------------------------------------------
//----------- USE datatabase as default ----------
if (empty($defaultDbName)) {
echo "USE $dbname";
$sqlQuery = 'USE `' . $dbname . '`;';
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
}
//------------------------------------------------
//------------ CREATE TABLE ----------------------
echo "CREATE TABLE example IF NOT EXISTS";
$sqlQuery = 'CREATE TABLE IF NOT EXISTS `example` (`id` INT AUTO_INCREMENT, `name` VARCHAR(255), PRIMARY KEY(`id`)) ENGINE=InnoDb;';
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
//------------------------------------------------
//------------ DROP TRIGGER IF EXISTS ------------
echo "DROP TRIGGER IF EXISTS";
$sqlQuery = 'DROP TRIGGER IF EXISTS `tr_example_bi_fill`;';
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
//------------------------------------------------
//--------------- CREATE TRIGGER ---------------------
echo "CREATE TRIGGER";
$sqlQuery = "
CREATE TRIGGER
`tr_example_bi_fill`
BEFORE INSERT ON
`example`
FOR EACH ROW BEGIN
SET new.`name` = CONCAT(new.`name`, '_TRIGGER');
END
;
";
echo ", DONE.\n";
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
//------------------------------------------------
//--------------- INSERT INTO --------------------
$value = rand(0,9999);
echo "INSERT INTO TABLE example VALUE '$value'";
$sqlQuery = "INSERT INTO `example` (`name`) VALUES ('$value')";
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
//------------------------------------------------
// --------------- SELECT FROM -------------------
echo "SELECT FROM example";
$sqlQuery = "SELECT `name` FROM `example` ORDER BY `id` DESC LIMIT 1;";
try {
$stmt = $pdo->query($sqlQuery);
} catch (\Exception $e) {
$msg = 'Could not execute query: "' . $sqlQuery . '"';
$msg .= '. PDO exception Msg: ' . $e->getMessage();
throw new \RuntimeException($msg);
}
echo ", DONE.\n";
//------------------------------------------------
$result = $stmt->fetchColumn();
echo "Result:\n";
print_r($result);
echo "\n=================\n";
然后我得到:
致命错误:未捕获运行时异常:无法执行查询:“USE
pdo_片段
;”。PDO异常消息:SQLSTATE[HY000]:一般错误:
其他未缓冲查询处于活动状态时,2014无法执行查询。
考虑使用pdoCalp::FutAccess()。或者,如果您的代码
只在mysql上运行,您可以启用查询
通过设置PDO::MYSQL\u ATTR\u USE\u BUFFERED\u QUERY属性进行缓冲
在第二次运行脚本时使用:
$dsn = 'mysql:host=' . $host;
$dsn = 'mysql:dbname=' .$dbname. ';host=' . $host;
首先,USE语句引发的异常会引发另一个异常:
致命错误:未捕获运行时异常:无法执行查询:
“如果存在触发器,则丢弃触发器”tr_示例_bi_fill
”。PDO异常消息:
SQLSTATE[HY000]:一般错误:2014无法在
其他未缓冲查询处于活动状态。考虑使用
PDO语句::fetchAll()。或者,如果您的代码只是
要在mysql上运行,可以通过设置
PDO::MYSQL\u ATTR\u USE\u BUFFERED\u查询属性
我想问一下,如何使用PDO连接到数据库的signle实例,并将选项设置为false,并且能够执行use database name代码>或<代码>下拉触发器代码>创建触发器代码>
它使我对侧重于无缓冲查询的错误消息感到困惑
IMO对于缓冲/非缓冲查询和使用$options[\PDO::MYSQL\u ATTR\u USE\u buffered\u QUERY]=false没有问题
或$options[\PDO::MYSQL\u ATTR\u USE\u BUFFERED\u QUERY]=true代码>没有帮助。
也许你能让我明白那个错误
经过一些额外的测试后,我认为问题可能与无缓冲查询有关,因为如果在第二次运行脚本时,我运行脚本时添加了:
$options[\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY] = false;
然后,脚本在以下时间更早地失败:
致命错误:未捕获运行时异常:无法执行查询:
如果不存在,则创建表示例
(id
INT AUTO\u INCREMENT,name
VARCHAR(255),主键(id
)引擎=InnoDb;”。PDO异常消息:
SQLSTATE[HY000]:一般错误:2014无法在
其他未缓冲查询处于活动状态。考虑使用
PDO语句::fetchAll()。或者,如果您的代码只是
要在mysql上运行,可以通过设置
PDO::MYSQL\u ATTR\u USE\u BUFFERED\u查询属性
使用下拉触发器(如果存在)未到达有问题的行
因此,看起来至少对于CREATE TABLE这样的语句,解决方案可以是使用$options[\PDO::MYSQL\u ATTR\u use\u BUFFERED\u QUERY]=true
,我相信这在默认情况下是正确的。但是,USE…
和CREATE TRIGGER…
,DROP TRIGGER…
的问题仍然存在
我正在使用:
PHP 7.3.8(cli)(构建时间:2019年8月2日05:16:32)(新南威尔士州)
与MySQL相关的扩展:PDO 7.3.8、mysqli 7.3.8、mysqlnd 5.0.12-dev、PDO_mysq 7.3.8
MySQL 8.0.19
两者都基于Docker的官方图片。您的代码是错误的
看
这个问题没有足够的信息。您能从这段代码中删除每一条try-catch语句,再次运行它并提供您得到的确切输出吗?另外,PHP版本以及phpinfo()outputFWIW中是否提到“mysqlnd”我在尝试使用simulate_prepares set为false时遇到了很多问题,并且总是让PDO通过将其设置为true来处理事情。也就是说,您使用的是什么版本的PHP和MySQL,以及使用的是什么版本的mysqlnd?@YourCommonSense我编辑了这个问题,因此更明显的是引发了什么异常,以及何时在最后添加了PHP版本及其扩展。@Dave在最后编辑了这个问题。不幸的是,我可能用echo语句误导了您这是错误的(我更改了它)实际查询:$sqlQuery='DROP TRIGGER IF EXISTStr_example\u bi_fill
;当PDO::ATTR_EMULATE_PREPARES设置为true时,它是正确的,并且运行良好<代码>使用…
语句也可以正常工作,但当PDO::ATTR\u SIMULATE\u PREADES设置为false时,这两个语句都会失败。为什么必须为false?这似乎是一个bug,它存在了很长一段时间,还没有修复。如果php的新prelereas已经修复,那么您应该尝试使用它。jetSetting PDO::ATTR_EMULATE_PREPARES to FALSE允许在插入中使用。这在一次插入大量错误时速度更快。只需关闭第一个连接并打开第二个连接即可。如果必须在两者之间切换,请将两者都打开
DROP TRIGGER IF EXISTS tr_example_bi_fill