我之前从未使用过mysqli_multi_query而且它让我的大脑难以置信,我在网上找到的任何例子都无法帮助我弄清楚我想要做什么。
这是我的代码:
<?php
$link = mysqli_connect("server", "user", "pass", "db");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$agentsquery = "CREATE TEMPORARY TABLE LeaderBoard (
`agent_name` varchar(20) NOT NULL,
`job_number` int(5) NOT NULL,
`job_value` decimal(3,1) NOT NULL,
`points_value` decimal(8,2) NOT NULL
);";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`, `job_number`, `job_value`, `points_value`) SELECT agent_name, job_number, job_value, points_value FROM jobs WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`) SELECT DISTINCT agent_name FROM apps WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "SELECT agent_name, SUM(job_value), SUM(points_value) FROM leaderboard GROUP BY agent_name ORDER BY SUM(points_value) DESC";
$i = 0;
$agentsresult = mysqli_multi_query($link, $agentsquery);
while ($row = mysqli_fetch_array($agentsresult)){
$number_of_apps = getAgentAppsWeek($row['agent_name'],$weeknum,$current_year);
$i++;
?>
<tr class="tr<?php echo ($i & 1) ?>">
<td style="font-weight: bold;"><?php echo $row['agent_name'] ?></td>
<td><?php echo $row['SUM(job_value)'] ?></td>
<td><?php echo $row['SUM(points_value)'] ?></td>
<td><?php echo $number_of_apps; ?></td>
</tr>
<?php
}
?>
我要做的就是运行多个查询,然后使用这4个查询的最终结果并将它们放入我的表中。
上面的代码根本不起作用,我只是得到以下错误:
警告:mysqli_fetch_array()期望 参数1是mysqli_result, 给出的布尔值 C:\ XAMPP \ htdocs中\ hydroboard \ hydro_reporting_2010.php 在第391行
任何帮助?
答案 0 :(得分:8)
从manual:mysqli_multi_query()
返回bool
表示成功。
要从第一个查询中检索结果集,可以使用mysqli_use_result()或mysqli_store_result()。可以使用mysqli_more_results()和mysqli_next_result()处理所有后续查询结果。
这是一个返回多查询的最后结果的函数:
function mysqli_last_result($link) {
while (mysqli_more_results($link)) {
mysqli_use_result($link);
mysqli_next_result($link);
}
return mysqli_store_result($link);
}
用法:
$link = mysqli_connect();
$query = "SELECT 1;";
$query .= "SELECT 2;";
$query .= "SELECT 3";
mysqli_multi_query($link, $query);
$result = mysqli_last_result($link);
$row = $result->fetch_row();
echo $row[0]; // prints "3"
$result->free();
mysqli_close($link);
答案 1 :(得分:3)
好的经过一些摆弄,试验和错误,并参考我在谷歌搜索中遇到的另一篇文章,我设法解决了我的问题!
这是新代码:
<?php
$link = mysqli_connect("server", "user", "pass", "db");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$agentsquery = "CREATE TEMPORARY TABLE LeaderBoard (
`agent_name` varchar(20) NOT NULL,
`job_number` int(5) NOT NULL,
`job_value` decimal(3,1) NOT NULL,
`points_value` decimal(8,2) NOT NULL
);";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`, `job_number`, `job_value`, `points_value`) SELECT agent_name, job_number, job_value, points_value FROM jobs WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`) SELECT DISTINCT agent_name FROM apps WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "SELECT agent_name, SUM(job_value), SUM(points_value) FROM leaderboard GROUP BY agent_name ORDER BY SUM(points_value) DESC";
mysqli_multi_query($link, $agentsquery) or die("MySQL Error: " . mysqli_error($link) . "<hr>\nQuery: $agentsquery");
mysqli_next_result($link);
mysqli_next_result($link);
mysqli_next_result($link);
if ($result = mysqli_store_result($link)) {
$i = 0;
while ($row = mysqli_fetch_array($result)){
$number_of_apps = getAgentAppsWeek($row['agent_name'],$weeknum,$current_year);
$i++;
?>
<tr class="tr<?php echo ($i & 1) ?>">
<td style="font-weight: bold;"><?php echo $row['agent_name'] ?></td>
<td><?php echo $row['SUM(job_value)'] ?></td>
<td><?php echo $row['SUM(points_value)'] ?></td>
<td><?php echo $number_of_apps; ?></td>
</tr>
<?php
}
}
?>
在每次查询中多次粘贴mysqli_next_result后神奇地工作了!好极了!我明白为什么它有效,因为我告诉它跳过下一个结果3次,所以它跳到查询#4的结果,这是我想要使用的。
虽然看起来有点笨拙,但是如果你问我的话,应该有一个类似mysqli_last_result($ link)之类的命令......
感谢帮助rik和f00,我最终到达那里:)
答案 2 :(得分:1)
我会通过创建一个存储过程来简化您要做的事情,该存储过程将产生领导者/代理统计数据,然后从您的php(单个调用)中调用它,如下所示:
完整的脚本:http://pastie.org/1451802
或者,您可以将各个查询组合成一个选择/分组语句。
select
leaders.agent_name,
sum(leaders.job_value) as sum_job_value,
sum(leaders.points_value) as sum_points_value
from
(
select
agent_name,
job_number,
job_value,
points_value
from
jobs
where
year(booked_date) = 2011 and weekofyear(booked_date) = 2
union all
select distinct
agent_name,
0,0,0
from
apps
where
year(booked_date) = 2011 and weekofyear(booked_date) = 2
) leaders
group by
agent_name
order by sum_points_value desc;
drop procedure if exists list_leaders;
delimiter #
create procedure list_leaders
(
in p_year smallint unsigned,
in p_week tinyint unsigned
)
begin
create temporary table tmp_leaders(
agent_name varchar(20) not null,
job_number int unsigned not null default 0, -- note the default values
job_value decimal(3,1) not null default 0,
points_value decimal(8,2) not null default 0
)engine=memory;
insert into tmp_leaders (agent_name, job_number, job_value, points_value)
select agent_name, job_number, job_value, points_value from jobs
where year(booked_date) = p_year and weekofyear(booked_date) = p_week;
insert into tmp_leaders (agent_name) -- requires default values otherwise you will get nulls
select distinct agent_name from apps
where year(booked_date) = p_year and weekofyear(booked_date) = p_week;
select
agent_name,
sum(job_value) as sum_job_value,
sum(points_value) as sum_points_value
from
tmp_leaders
group by
agent_name order by sum_points_value desc;
drop temporary table if exists tmp_leaders;
end#
delimiter ;
call list_leaders(year(curdate()), weekofyear(curdate()));
<?php
ob_start();
try
{
$db = new mysqli("localhost", "foo_dbo", "pass", "foo_db", 3306);
if ($db->connect_errno)
throw new exception(sprintf("Could not connect: %s", $db->connect_error));
$sqlCmd = "call list_leaders(2011, 2)";
$result = $db->query($sqlCmd);
if(!$result) throw new exception(sprintf("Invalid query : %s", $sqlCmd));
if($db->affected_rows <= 0){
echo "no leaders found !";
}
else{
$leaders = $result->fetch_all(MYSQLI_ASSOC);
foreach($leaders as $ldr){
// do stuff
echo $ldr["agent_name"], "<br/>";
}
}
}
catch(exception $ex)
{
ob_clean();
echo sprintf("zomg borked - %s", $ex->getMessage());
}
if(!$db->connect_errno) $db->close();
ob_end_flush();
?>
现在有点简单 - 希望它有所帮助:)
答案 3 :(得分:1)
将结果存储在变量中,最后使用该变量。
do{
if($result = $con->store_result()){
$data=$result->fetch_all();
$result->free();
}
} while($con->more_results()&&$con->next_result());
echo(json_encode($data));
答案 4 :(得分:0)
我想整理海报目前接受的解决方案,使其更符合我认为最佳做法。
IMO这个更容易阅读。
if(mysqli_multi_query($link,$agentsquery)){
do{
if($result=mysqli_store_result($link)){ // ignore if no record set
while($row=mysqli_fetch_array($result)){
echo "<tr class=\"tr",(++$i & 1),"\">";
echo "<td style=\"font-weight:bold;\">",$row['agent_name'],"</td>";
echo "<td>",$row['SUM(job_value)'],"</td>";
echo "<td>",$row['SUM(points_value)'],"</td>";
echo "<td>",getAgentAppsWeek($row['agent_name'],$weeknum,$current_year),"</td>";
echo "</tr>";
}
mysqli_free_result($result);
}
} while(mysqli_more_results($link) && mysqli_next_result($link));
}
if($error_mess=mysqli_error($link)){
echo "<tr class=\"error\"><td colspan=\"4\">Error: $error_mess</td></tr>";
}
//if any query returns false, mysqli_multi_query will stop
// and the individual query error to blame will be provided.
答案 5 :(得分:0)
我想我也会在这个问题上把我的帽子戴在戒指上(嘿,它仍然是程序性的,所有的爵士乐)。这不是万无一失的,但是我和MySQLi以及参与multi_query的快乐乐队一起战斗和战斗,我无法按照我想要的方式进行游戏,或者具有灵活性我需要。我看到了一些例子,其中一些程序员只是在运行explode(';', $sql_statements)
,这让我的眼睛流下了可怕的错误。
我的解决方案可能不适合您,但这对我有用。 (不,它也不是防弹,但是为我的特定应用做了工作)。
<?php
$file = file_get_contents('test_multiple_queries.sql');
$result = preg_split("/;(?=\s*(create|insert|update|alter|show|explain|truncate|drop|delete|replace|start|lock|commit|rollback|set|begin|declare|rename|load|begin|describe|help))/im", $file);
$result = array_map('trim', $result);
foreach($result as $sql_query) {
// Procedural style
$my_query = mysqli_query($link, $sql_query);
// Now you can get errors easily, or affected_rows, or whatever
// using much simpler, readable code
mysqli_error($link);
mysqli_affected_rows($link);
// or go crazy with some other stuff
$words = preg_split("/\s+/", $sql_query);
switch(strtolower($words[0])) {
case 'insert':
// do something nifty like...
echo 'New ID: '.mysqli_insert_id($link)."\n";
break;
case 'drop':
// obviously run this before the query, simply here for example
echo 'Hey young (man|lady)! We don\'t drop anything!';
break;
case 'select':
// hooray for selecting stuff
while($rs = mysqli_fetch_assoc($my_query)) {
// have fun with data
}
break;
}
}