我正在尝试从perl脚本访问MySQL存储过程但是我收到此错误:
“无法在给定的上下文中返回结果集”
如您所见,下面的过程返回两个结果表。最初,我认为问题是由此导致的,但如果我调用只有一个select语句的存储过程,则会出现同样的错误。
这是proc:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `GetPictureDataForSendMsg`(memIdVal VARCHAR(4))
begin
select val, size3
from members
where memid=memIdVal;
select id, filename, picname, picsize
from pictures
where memid=memIdVal order by id asc;
end
由以下人员召集:
$input = 'ABC1';
$dbh = DBI->connect("DBI:mysql:$db:$server;mysql_multi_statements=true", "$user", "$password");
my $result = $dbh->prepare('CALL GetPictureDataForSendMsg($input)') or error($q, "Problem with database call");
$result->execute or error($q, "Problem with database call");
错误与execute语句相关联。我有必要的权限和MySQL的最新版本;该过程在命令行中运行完美。
怎么了?谢谢你的帮助。
答案 0 :(得分:3)
CALL ...语句周围有单引号。变量仅以双引号字符串进行插值,而不是单引号字符串。将这些更改为双引号,如下所示:
my $result = $dbh->prepare("CALL GetPictureDataForSendMsg($input)") or error($q, "Problem with database call");
这会将变量插入到字符串中,因此您现在将“CALL GetPictureDataForSendMsg(ABC1)”发送到数据库。这也行不通。数据库将把你作为参数提供的任何内容直接放入SQL字符串中。如果你引用ABC1就像这个'ABC1'那么它会看到它作为一个字符串;否则它会认为ABC1是列的名称 - 它不是。
所以,这一行将起作用:
my $result = $dbh->prepare("CALL GetPictureDataForSendMsg('$input')") or error($q, "Problem with database call");
但这条线路也存在问题。如果$ input表示的字符串包含单引号怎么办?它会破裂。这就是SQL注入攻击的发生方式。相反,你应该使用DBI引用函数,如下所示:
my $result = $dbh->prepare('CALL GetPictureDataForSendMsg('.$dbh->quote($input).')') or error($q, "Problem with database call");
我在我的MySQL实例(服务器版本:5.1.49-1ubuntu8.1(Ubuntu))上对此进行了测试,但它确实有效。