无法从perl脚本运行MySQL存储过程

时间:2011-06-29 20:15:14

标签: mysql perl stored-procedures

我正在尝试从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的最新版本;该过程在命令行中运行完美。

怎么了?谢谢你的帮助。

1 个答案:

答案 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))上对此进行了测试,但它确实有效。