我正在使用MySQLi编写一个PHP应用程序.在这个应用程序的运行过程中,我连续准备了许多SQL预准备语句,然后在整个应用程序过程中根据需要执行它们.
但是,当我在应用程序中运行相同的特定语句两次(使用特定参数)时,我会得到以下错误:mysqli_stmt::execute(): Premature EOF in result field metadata
.
为了进一步澄清我的问题,我附上了一个最小的可重复使用的代码示例.首先,我的数据库包含一个名为GET_USER_ID_FROM_USERNAME
的存储过程.顾名思义,它接受一个字符串用户名作为参数,判断用户名是否存在,然后返回两个值--一个标记为User_Exists
的布尔值,用于判断数据库中是否知道该用户名,以及一个标记为ID
的整数(如果前者是true
).以下是此过程的代码:
CREATE PROCEDURE GET_USER_ID_FROM_USERNAME (IN Username_Param TINYTEXT CHARSET utf8mb4)
BEGIN
IF ((SELECT COUNT(1) FROM Users WHERE Username = Username_Param) = 1) THEN
SELECT ID, TRUE AS User_Exists FROM Users WHERE Username = Username_Param;
ELSE
SELECT FALSE AS User_Exists;
END IF;
END
这完全符合我的要求-当我传入一个已知的用户名时,它在User_Exists
列中返回true
,在eps列中返回相关用户的ID
,当我传入一个不在数据库中的用户名时,它在User_Exists
列中返回false
.
当我调用这个过程twice(即使我调用中间的其他过程)并且只调用when the first time is an existing username and the second time is an unknown one(即,当第一次User_Exists
的值是true
,而第二次的值是false
)时,问题就出现了.我使用准备好的语句调用此 routine ,并将所需的用户名绑定到该语句.
以下是抛出所需错误的代码的最小示例:
// CONNECT
$mysqli = new mysqli("localhost", "root", "root", "test_database");
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli->autocommit(false);
$mysqli->set_charset('utf8mb4');
// PREPARE STATEMENT
$stmt = $mysqli->prepare("CALL GET_USER_ID_FROM_USERNAME (?);");
// BIND PARAMETER
$username = "";
$stmt->bind_param("s", $username);
// EXECUTE WITH KNOWN VALUE
$username = "Existing_Username";
$stmt->execute();
// Flush result (if I exclude this I get a "commands out of sync" error)
$stmt->get_result();
$mysqli->next_result();
// All fine so far
// EXECUTE WITH UNKNOWN VALUE
$username = "Fake_Username";
$stmt->execute(); // <- Error thrown here: mysqli_stmt::execute(): Premature EOF in result field metadata
在第一个用户名已知而第二个用户名未知的情况下,此(且仅此)配置会抛出错误.如果仅使用已知或未知用户名调用该语句一次,它将返回我所期望的结果.如果首先使用已知用户名调用该语句,然后使用不同的已知用户名调用该语句,它也会返回我所期望的结果.
查找错误消息Premature EOF in result field metadata
未产生任何结果.如果有人知道这条消息是如何或为什么出现的,或者知道我的代码做错了什么,我将不胜感激!
这是我为本例设置的Users
表:
CREATE TABLE Users (
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Username TINYTEXT NOT NULL,
Pass_Hash TINYTEXT NOT NULL
);
行:
ID - Username - Pass_Hash
------------------------------------------------------------------------------------------
1 Existing_Username $2y$10$l8y.GEK3LFnLyJWhAmHdg.7lMb45SezorBDODrqWUq4M0K1P3rDCq
(PASS_HASH为Password1
,已散列).
我在其上运行此程序的设置:
Windows上的MAMP
PHP 8.1.0
MySQL 5.7.24