gpt4 book ai didi

php - MySql PDO 和二级内部过程调用中抛出的异常

转载 作者:行者123 更新时间:2023-11-29 01:52:58 24 4
gpt4 key购买 nike

我们有以下情况...

DROP PROCEDURE IF EXISTS unit_throw_error;
CREATE PROCEDURE unit_throw_error() CALL throw_error();

DROP PROCEDURE IF EXISTS throw_error;
CREATE PROCEDURE throw_error() CALL _proc_does_not_exist();

如果您调用第一个过程 unit_throw_error,php PDO 对象将不会抛出通过第二个过程创建的异常。一些示例代码:

$dsn = "mysql:host=localhost;dbname=test";
$username = "...";
$password = "...";

$pdo = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

$query = "CALL unit_throw_error();";
$stmt = $pdo->prepare($query);
$stmt->execute();

do {
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} while ($stmt->nextRowset() && $stmt->columnCount());

$stmt->closeCursor();

预期的结果是抛出 PDOException 但这并没有发生。有什么想法吗?

编辑

我们已经将这种情况隔离为仅在抛出异常的行之前发生成功选择时发生...

-- CREATE DATABASE `exception_test` /*!40100 DEFAULT CHARACTER SET utf8 */;

use exception_test;

DROP TABLE if exists `test_data`;
CREATE TABLE `test_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`some_field` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

INSERT INTO `test_data` (`some_field`) VALUES ('sdf');
INSERT INTO `test_data` (`some_field`) VALUES ('fgh');
INSERT INTO `test_data` (`some_field`) VALUES ('ghj');

drop procedure if exists `unit_throw_error`;
create procedure unit_throw_error() call unit_throw_error_2();

drop procedure if exists `unit_throw_error_2`;
delimiter //
create procedure unit_throw_error_2()
begin

select * from test_data;

call unknown_procedure();

end//
delimiter ;

有谁知道为什么选择查询时不抛出异常?

最佳答案

处理存储过程时,you need to call next_result()方法,以便使 PDO 了解该过程返回的其他结果。

所以,代码应该是

$stmt = $pdo->prepare("CALL unit_throw_error()");
$stmt->execute();
do {
$data = $stmt->fetchAll();
var_dump($data);
} while ($stmt->nextRowset() && $stmt->columnCount());

在这种情况下,PDO 将从数据库中获取下一个结果,如果这个结果是错误的,则会抛出异常。

编辑:

似乎对于这种语法 错误的特殊情况(即甚至在执行之前发生的错误),您实际上不需要调用nextRowset()。相反,只需确保将 PDO 设置为 ERRMODE_EXCEPTION

但是,无论如何,nextRowset() 必须使用存储过程调用,以便让其他查询运行,并在需要多个结果集时得到错误。

因此(只是为了证明我的回答有用),如果您将代码更改为:

drop procedure if exists `unit_throw_error`;
create procedure unit_throw_error() call unit_throw_error_2();

drop procedure if exists `unit_throw_error_2`;
delimiter //
create procedure unit_throw_error_2()
begin

select * from test_data;
select * from non_existent;

end//
delimiter ;

并在不调用 nextRowset() 的情况下运行 PDO 代码,不会出现错误。但是使用我在上面发布的代码会抛出错误,

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'exception_test.non_existent' doesn't exist

关于php - MySql PDO 和二级内部过程调用中抛出的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36438176/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com