【问题标题】:PDOStatement::execute(): Premature end of data error when executing stored procedure [duplicate]PDOStatement::execute():执行存储过程时数据提前结束错误[重复]
【发布时间】:2015-11-21 15:24:38
【问题描述】:

我有一个可以在 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.17 我在我的盒子上使用最新的 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 和脚本能够运行就证明了这一点。以字符串形式返回正确的值。但是,如果我尝试将返回作为 1 或 0 的整数,我仍然可以从 SP 获得正确的返回输出,但是在输出之后立即添加 3 条 php 错误消息,并且它们没有提及“旧身份验证”。 为避免混淆和清晰起见,完整的错误消息如下:

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

在我发布之前,我确实花了相当多的时间寻找可能的解决方案,并且确实看到了该帖子并检查了我在 MySQL 中的密码,并且它正在使用新的身份验证...除非我遗漏了什么。下次在将帖子视为重复帖子之前请多加小心,因为从我的帖子中可以清楚地看出它不是。

也就是说,我们将不胜感激任何帮助。 PHP 瘾君子

【问题讨论】:

  • 请贴出你的参数绑定、存储过程以及MySQL和PHP的版本
  • 我提供了答案,希望对您有所帮助。

标签: php


【解决方案1】:

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

...: 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 ... 

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

【讨论】:

  • 嗨马库斯,不,错误并没有这么说。我在发布之前研究过那个...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2020-01-24
  • 1970-01-01
  • 2011-08-08
相关资源
最近更新 更多