正在 PHP 中使用游标执行存储过程
Executing a stored procedure with cursor in PHP
我有一个要从 php 调用的存储过程。这是存储过程:
BEGIN
DECLARE done INT DEFAULT FALSE;
declare phone_temp VARCHAR(20) default '';
declare phone_cur cursor for SELECT DISTINCT sentNum FROM Queue;
declare continue handler for not found set done = true;
#create temp table
create temporary table if not exists temp_return AS SELECT * FROM Queue LIMIT 0;
#empty if exists
delete from temp_return;
open phone_cur;
phone_loop: LOOP
fetch phone_cur into phone_temp;
if done then
leave phone_loop;
end if;
insert into temp_return SELECT * FROM Queue WHERE num2=phone_temp LIMIT 2;
insert into temp_return SELECT * FROM Queue WHERE num1=phone_temp LIMIT 1;
end loop phone_loop;
close phone_cur;
select * from temp_return;
drop table if exists temp_return;
END
直接在mysqlworkbench中调用即可。在 php 中,它不起作用。这是我的 php:
function grabFromSmsQueue(){
global $myStmt, $conn;
if(isset($myStmt)){
$myStmt -> execute();
}
else{
$query = "CALL myStoredProc();";
$myStmt = $conn->stmt_init();
$myStmt -> prepare($query);
$myStmt -> execute();
}
$result = $myStmt -> get_result();
//print_r ($result);
$info = [];
if(isset($result)){
while($data = $result->fetch_assoc()){
$info[] = $data;
}
}
return $info;
}
这样连接,出现如下错误
The localhost page isn’t working
localhost didn’t send any data.
ERR_EMPTY_RESPONSE
我将我的问题追溯到 $data = $result->fetch_assoc()
的问题,因为当我将其注释掉并放入 print_r
时,我得到了实际返回的内容,即 mysqli_result Object ( [current_field] => 0 [field_count] => 9 [lengths] => [num_rows] => 0 [type] => 1 )
。我得出的结论是它不起作用,因为 [num_rows] => 0
.
现在,回到我的存储过程,我删除了所有提到的游标并将其替换为硬编码值,它在 workbench 和 php 中都有效。我已经验证通过 php 连接的用户具有权限,连接已打开,并且相同的代码可以执行其他存储过程(不包括游标的存储过程)。这是否意味着我不能在 php 调用的存储过程中使用游标?有游标的替代品吗?我的 php 语法中是否缺少处理游标的内容?
基于 3 个分组的聊天讨论,这提供了 SQLFiddle 测试数据(那里的数据不多)。
由于测试数据的滑动 window 其中 now()
与该数据相关,因此使用以下变量 "freeze" now()
。只是为了方便测试和验证输出。
因此,最终放弃并更改代码中使用它的 4 个引用(请注意第 3 组使用它两次)。
now()
变量:
select @theNow:=now();
-- REM OUT the following line. It is used only for testing (as now will chg, your data won't)
select @theNow:='2016-06-23 14:00:00';
查询:
select id,sentNum,message,sentTime,startAtTime,sentByTime,msgType,theGrp from
( select id,sentNum,message,sentTime,startAtTime,sentByTime,msgType,theGrp,
if(sentNum!=@lastSentNum,greatest(@sentNumChg:=1,0),least(@sentNumChg:=0,1)) as dummy1,
if(theGrp!=@lastGrp,greatest(@grpChg:=1,0),least(@grpChg:=0,1)) as dummy2,
if(@sentNumChg=1 or @grpChg=1,@seqNum:=1,@seqNum:=@seqNum+1) as seqNum,
@lastSentNum:=sentNum as setLast01,
@lastGrp:=theGrp as setLast02
from
( -- GROUP 1: sentByTime<=now(), INVITE
select `id`, `sentNum`, `message`, `sentTime`, `startAtTime`, `sentByTime`, `msgType`, 1 as theGrp
from SmsQueue
where sentByTime<=@theNow and msgType='invite'
UNION ALL
-- GROUP 2 startAtTime<=now(), BROADCAST
select `id`, `sentNum`, `message`, `sentTime`, `startAtTime`, `sentByTime`, `msgType`, 2 as theGrp
from SmsQueue
where startAtTime<=@theNow and msgType='broadcast'
UNION ALL
-- GROUP 3: sentByTime>now() && startAtTime<=now(), INVITE
select `id`, `sentNum`, `message`, `sentTime`, `startAtTime`, `sentByTime`, `msgType`, 3 as theGrp
from SmsQueue
where sentByTime>@theNow and startAtTime<=@theNow and msgType='invite'
) d1
cross join (select @sentNumChg:=0,@grpChg:=0,@lastSentNum:='',@lastGrp:=0,@seqNum:=0) as xParams
order by sentNum,theGrp,sentByTime,id -- id is the tie-break
) d2
where (theGrp=1 and seqNum<3) or (theGrp=2 and seqNum=1) or (theGrp=3 and seqNum=1)
order by sentNum,theGrp;
输出(我的客户端工具目前是文本挑战):
请参阅我的 this 答案顶部的一般性评论以了解高级变量用法。
我有一个要从 php 调用的存储过程。这是存储过程:
BEGIN
DECLARE done INT DEFAULT FALSE;
declare phone_temp VARCHAR(20) default '';
declare phone_cur cursor for SELECT DISTINCT sentNum FROM Queue;
declare continue handler for not found set done = true;
#create temp table
create temporary table if not exists temp_return AS SELECT * FROM Queue LIMIT 0;
#empty if exists
delete from temp_return;
open phone_cur;
phone_loop: LOOP
fetch phone_cur into phone_temp;
if done then
leave phone_loop;
end if;
insert into temp_return SELECT * FROM Queue WHERE num2=phone_temp LIMIT 2;
insert into temp_return SELECT * FROM Queue WHERE num1=phone_temp LIMIT 1;
end loop phone_loop;
close phone_cur;
select * from temp_return;
drop table if exists temp_return;
END
直接在mysqlworkbench中调用即可。在 php 中,它不起作用。这是我的 php:
function grabFromSmsQueue(){
global $myStmt, $conn;
if(isset($myStmt)){
$myStmt -> execute();
}
else{
$query = "CALL myStoredProc();";
$myStmt = $conn->stmt_init();
$myStmt -> prepare($query);
$myStmt -> execute();
}
$result = $myStmt -> get_result();
//print_r ($result);
$info = [];
if(isset($result)){
while($data = $result->fetch_assoc()){
$info[] = $data;
}
}
return $info;
}
这样连接,出现如下错误
The localhost page isn’t working
localhost didn’t send any data.
ERR_EMPTY_RESPONSE
我将我的问题追溯到 $data = $result->fetch_assoc()
的问题,因为当我将其注释掉并放入 print_r
时,我得到了实际返回的内容,即 mysqli_result Object ( [current_field] => 0 [field_count] => 9 [lengths] => [num_rows] => 0 [type] => 1 )
。我得出的结论是它不起作用,因为 [num_rows] => 0
.
现在,回到我的存储过程,我删除了所有提到的游标并将其替换为硬编码值,它在 workbench 和 php 中都有效。我已经验证通过 php 连接的用户具有权限,连接已打开,并且相同的代码可以执行其他存储过程(不包括游标的存储过程)。这是否意味着我不能在 php 调用的存储过程中使用游标?有游标的替代品吗?我的 php 语法中是否缺少处理游标的内容?
基于 3 个分组的聊天讨论,这提供了 SQLFiddle 测试数据(那里的数据不多)。
由于测试数据的滑动 window 其中 now()
与该数据相关,因此使用以下变量 "freeze" now()
。只是为了方便测试和验证输出。
因此,最终放弃并更改代码中使用它的 4 个引用(请注意第 3 组使用它两次)。
now()
变量:
select @theNow:=now();
-- REM OUT the following line. It is used only for testing (as now will chg, your data won't)
select @theNow:='2016-06-23 14:00:00';
查询:
select id,sentNum,message,sentTime,startAtTime,sentByTime,msgType,theGrp from
( select id,sentNum,message,sentTime,startAtTime,sentByTime,msgType,theGrp,
if(sentNum!=@lastSentNum,greatest(@sentNumChg:=1,0),least(@sentNumChg:=0,1)) as dummy1,
if(theGrp!=@lastGrp,greatest(@grpChg:=1,0),least(@grpChg:=0,1)) as dummy2,
if(@sentNumChg=1 or @grpChg=1,@seqNum:=1,@seqNum:=@seqNum+1) as seqNum,
@lastSentNum:=sentNum as setLast01,
@lastGrp:=theGrp as setLast02
from
( -- GROUP 1: sentByTime<=now(), INVITE
select `id`, `sentNum`, `message`, `sentTime`, `startAtTime`, `sentByTime`, `msgType`, 1 as theGrp
from SmsQueue
where sentByTime<=@theNow and msgType='invite'
UNION ALL
-- GROUP 2 startAtTime<=now(), BROADCAST
select `id`, `sentNum`, `message`, `sentTime`, `startAtTime`, `sentByTime`, `msgType`, 2 as theGrp
from SmsQueue
where startAtTime<=@theNow and msgType='broadcast'
UNION ALL
-- GROUP 3: sentByTime>now() && startAtTime<=now(), INVITE
select `id`, `sentNum`, `message`, `sentTime`, `startAtTime`, `sentByTime`, `msgType`, 3 as theGrp
from SmsQueue
where sentByTime>@theNow and startAtTime<=@theNow and msgType='invite'
) d1
cross join (select @sentNumChg:=0,@grpChg:=0,@lastSentNum:='',@lastGrp:=0,@seqNum:=0) as xParams
order by sentNum,theGrp,sentByTime,id -- id is the tie-break
) d2
where (theGrp=1 and seqNum<3) or (theGrp=2 and seqNum=1) or (theGrp=3 and seqNum=1)
order by sentNum,theGrp;
输出(我的客户端工具目前是文本挑战):
请参阅我的 this 答案顶部的一般性评论以了解高级变量用法。