PDOStatement::execute():执行存储过程时过早结束数据错误


PDOStatement::execute(): Premature end of data error when executing stored procedure

我有一个存储过程,它在MySQL中运行良好,只返回一个值。

然而,当尝试用PHP调用它时,它会返回正确的值,但也会返回以下三个错误

Warning: PDOStatement::execute(): Premature end of data (mysqlnd_wireprotocol
Warning: PDOStatement::execute(): RSET_HEADER packet 1 bytes shorter than expected 
Warning: PDOStatement::execute(): Error reading result set's header 

它们都指第90行我通过PDO参数化查询执行SP

$Statement->execute();

有人知道我为什么会犯这些错误吗?谷歌搜索主要指的是在被拒绝使用"旧"风格的密码访问数据库时获得此信息。我没有这个问题,因为SP正在返回正确的值,但有三条错误消息。

嗨,马库斯,谢谢你的回复。对不起,我离开了。我的PHP版本是5.5.12,MySQL版本是5.6.7。我在盒子上使用最新的WampServer。错误消息中没有提到"使用旧密码"。目前,我使用以下代码使SP正常工作,但我必须将SP结果作为VARCHAR返回,然后用PHP将"true/false"字符串转换为bool。如果我尝试将SP值作为INT返回,这就是我得到错误的时候。。。

存储过程:

CREATE DEFINER=`MyDB`@`localhost` PROCEDURE `new_account`(
IN Cus_Title VARCHAR(4),
IN Cus_Name VARCHAR(35),
IN Cus_Surname VARCHAR(35),
IN Cus_Email VARCHAR(75),
IN Cus_Password VARBINARY(255),
IN Cus_Status TINYINT(1),
IN Cus_LoginIP VARCHAR(45),
IN Cus_Created TIMESTAMP,
IN Pho_Number VARCHAR(14),
IN Com_Name VARCHAR(50),
IN Com_BuildingNumber VARCHAR(14),
IN Com_Address VARCHAR(100),
IN Com_Street VARCHAR(35),
IN Com_City VARCHAR(25),
IN Com_County VARCHAR(35),
IN Com_PostCode VARCHAR(12),
IN Act_ActivationToken VARBINARY(255),
IN Act_Expiry TIMESTAMP,
-- OUT ReturnStatus INT(3) using this I get errors from PHP
OUT ReturnStatus VARCHAR(5)
)
BEGIN
DECLARE Cus_ID INT(11) UNSIGNED; -- CustomerID
DECLARE Com_ID INT(11) UNSIGNED; -- CompanyID
IF EXISTS(SELECT Email FROM customers WHERE Email = Cus_Email) THEN
SET ReturnStatus = "false";
SELECT ReturnStatus;
ELSE
INSERT INTO customers(Title, Name, Surname, Email, Password, Status, LoginIP, Created)
VALUES(Cus_Title, Cus_Name, Cus_Surname, Cus_Email, Cus_Password, Cus_Status, Cus_LoginIP, Cus_Created);
SET Cus_ID = LAST_INSERT_ID();

IF(Pho_Number != '') THEN -- Customer has registered a mobile number
INSERT INTO customers_phones(CustomerID, Type, Number)
VALUES(Cus_ID, 'Mobile', Pho_Number);
END IF;
IF EXISTS(SELECT ID, Name, PostCode FROM companys WHERE Name = Com_Name AND PostCode = Com_PostCode) THEN
SET Com_ID = (SELECT ID FROM companys WHERE Name = Com_Name AND PostCode = Com_PostCode);
ELSE
INSERT INTO companys(Name, BuildingNumber, Address, Street, City, County, PostCode)
VALUES(Com_Name, Com_BuildingNumber, Com_Address, Com_Street, Com_City, Com_County, Com_PostCode);
SET Com_ID = LAST_INSERT_ID();
END IF;
INSERT INTO customers_order_delivery(CustomerID, CompanyID)
VALUES(Cus_ID, Com_ID);
INSERT INTO customers_activations(CustomerID, ActivationToken, Expiry)
VALUES(Cus_ID, Act_ActivationToken, Act_Expiry);
INSERT INTO customers_subscriptions(CustomerID, Type, Method)
VALUES(Cus_ID, 'Newsletter', 'Email');
SET ReturnStatus = 'true';
SELECT ReturnStatus;
END IF;
END;

PHP bindings are as follows and are contained within a try/catch block:
$SQL = 'call new_account(:Cus_Title, :Cus_Name, :Cus_Surname, :Cus_Email, :Cus_Password, :Cus_Status, :Cus_LoginIP, :Cus_Created, :Pho_Mobile, :Com_Name, :Com_BuildingNumber, :Com_Address, :Com_Street, :Com_County, :Com_City, :Com_PostCode, :Act_ActivationToken, :Act_Expiry, :ReturnStatus)';
$Statement = $Connection->prepare($SQL);
#Bind parameters
$Statement->bindParam(':Cus_Title', $_Form->Validated['Title']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Cus_Name', $_Form->Validated['Name']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Cus_Surname', $_Form->Validated['Surname']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Cus_Email', $_Form->Validated['Email']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Cus_Password', $_Form->Validated['Password']['input'], PDO::PARAM_LOB);
$Statement->bindParam(':Cus_Status', $_Form->Validated['UserStatus']['input'], PDO::PARAM_INT);
$Statement->bindParam(':Cus_LoginIP', $_Form->Validated['LoginIP']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Cus_Created', $_Form->Validated['CreatedOn']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Pho_Mobile', $_Form->Validated['Mobile']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Act_ActivationToken', $_Form->Validated['ActivationToken']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Act_Expiry', $_Form->Validated['Expiry']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Com_Name', $_Form->Validated['Company']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Com_BuildingNumber', $_Form->Validated['BuildingNumber']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Com_Address', $_Form->Validated['Address']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Com_Street', $_Form->Validated['Street']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Com_City', $_Form->Validated['City']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Com_County', $_Form->Validated['County']['input'], PDO::PARAM_STR);
$Statement->bindParam(':Com_PostCode', $_Form->Validated['PostCode']['input'], PDO::PARAM_STR);
$Statement->bindParam(':ReturnStatus', $ReturnStatus, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 3);
$Statement->execute();
$AccountCreationStatus = $Statement->fetchColumn();  //Check the account was successfully created

$AccountCreationStatus = ($AccountCreationStatus == 'true') ? true : false; // Convert return from SP as currently its buggy as cannot return INT or BOOL
if($AccountCreationStatus){ // New account was successfully created
#Send new user activation email

你好,R3uK、EdChum、Wtower、Rajesh和pinkal我的帖子不是重复的,因为在引用的解决方案中在这种情况下,他们谈到无法连接到MySQL。如果你们仔细阅读我的帖子,你们会发现我可以很好地连接到MySQL,我的SP和脚本能够运行就是明证。以字符串形式返回正确的值。然而,如果我尝试将返回值作为int值1或0,我仍然可以从SP获得正确的返回输出,但在输出后立即添加了3条php错误消息,并且它们没有提及"旧身份验证"。为了避免混淆和清晰起见,错误消息全文如下:

    • (!)警告:未知:第0行"未知"中的数据(mysqlnd_wireprotocol.c:1116)过早结束
    • (!)警告:未知:RSET_HEADER数据包比第0行"未知"中的预期短1字节
    • (!)警告:未知:读取第0行"未知"中的结果集标头时出错

同样在我发帖之前,我确实花了相当多的时间搜索可能的解决方案,确实看到了那篇帖子,并在MySQL中检查了我的密码,它正在使用新的身份验证。。。除非我错过了什么。下次在将帖子视为重复之前,请再小心一点,因为从我的帖子中可以清楚地看出,它不是。

也就是说,任何帮助都将不胜感激。PHP Addict

我想你只是跳过了帖子中的一些信息,所以完整的错误消息听起来像这样:

...: Premature end of data (mysqlnd_wireprotocol.c:554) in ...
...: OK packet 1 bytes shorter than expected in ...
...: mysqlnd cannot connect to MySQL XXX using the old insecure authentication. Please use an administration tool to reset your password with the command SET PASSWORD = PASSWORD('your_existing_password'). This will store a new, and more secure, hash value in mysql.user. If this user is used in other scripts executed by PHP XXX or earlier you might need to remove the old-passwords flag from your my.cnf file in ... 

如果是这样,您可以按照错误文本中的信息轻松解决问题。您可以在此处找到更多详细信息。