- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
如何使用准备好的语句(或其他对 SQL 注入(inject)同样安全的查询方法)在同一个 mysqli 连接中调用两个 MySQL 存储过程,而不会出现以下错误:
Warning: Packets out of order. Expected 1 received 61. Packet size=7 in /...
Warning: mysqli::prepare(): MySQL server has gone away in /...
在 tutorialspoint 上在线连接了代码
我正在用 MySQL 数据库制作一个 PHP 后端。我想从一个查询中获得两个结果:每周摘要列表和所有周摘要。
┌───────┬────────────┬────────────┬─────
| Week | Sales | Commission | ...
├───────┼────────────┼────────────┼─────
| week1 | $7,912.12 | $923.41 | ...
| week2 | $6,423.48 | $824.87 | ...
| week3 | $8,180.67 | $634.04 | ...
| ... | ... | ... | ...
├───────┼────────────┼────────────┼─────
| total | $67,012.23 | $7,532.58 | ...
| avg | $7,012.54 | $787.38 | ...
└───────┴────────────┴────────────┴─────
我以前只是把每周的总结存储在一个数据库表中,然后使用存储过程来获取所有每周总结的摘要。在我的 PHP 代码中,我只是选择了 week
表中的所有行,然后调用了 getWeeksSummary
存储过程。
现在我必须能够过滤每周摘要中的数据。我用存储过程 getWeeks()
替换了一个简单的 SELECT ... FROM week
来计算所有每周摘要。
$weeksSummary = new stdClass();
if ($stmt = $mysqli->prepare('CALL getWeeks(?,?,?);')) {
$stmt->bind_param('sss', $a, $b, $c);
$stmt->execute();
$stmt->bind_result($week, $sales, $commission, ...);
$weeksSummary->weeks = [];
while($stmt->fetch())
{
$week = new stdClass();
$week->week = $week;
$week->sales = $sales;
$week->commission = $commission;
...
$weeksSummary->weeks[] = $week;
}
$stmt->free_result();
$stmt->close();
}
if ($stmt = $mysqli->prepare('CALL getWeeksSummary(?,?,?);')) {
$stmt->bind_param('sss', $a, $b, $c);
$stmt->execute();
$stmt->bind_result($avgSales, $totSales, $avgCommission, $totCommission ...);
$stmt->fetch();
$weeksSummary->summary = new stdClass();
$weeksSummary->summary->avgSales = $avgSales;
$weeksSummary->summary->totSales = $totSales;
$weeksSummary->summary->avgCommission = $avgCommission;
$weeksSummary->summary->totCommission = $totCommission;
...
$stmt->free_result();
$stmt->close();
}
echo json_encode($weeksSummary);
当第一个准备语句是 SELECT week, sales, commission, ... FROM week WHERE a=?, b=?, c=?;
而不是 时,这段代码工作正常CALL getWeeks(?,?,?);
.现在我得到这些错误:
Warning: Packets out of order. Expected 1 received 61. Packet size=7 in /...
Warning: mysqli::prepare(): MySQL server has gone away in /...
1) 失败: 我为第二个查询使用了一个新的语句对象 $stmt2
。同样的错误。
2) 成功: 我关闭了 mysqli
连接并在第二个语句之前打开了一个新连接。第二个 mysqli
连接与它自己的准备语句确实运行良好,但连接到数据库的代码保持完全独立,所以这并没有真正帮助。
3) 失败: 出于好奇,我回到原来的工作代码并重新排序语句,将存储过程放入SELECT
语句之前的语句。同样的错误。因此 mysqli
连接在存储过程之前 查询时正常,但不喜欢存储过程之后 的任何查询。
4) 失败: 我尝试将 $mysqli->next_result();
放在第一条语句之后。同样的错误。但是,如果我使用 query()
而不是 prepare()
来调用存储过程,则 next_result()
确实允许这两个存储过程运行。不过,我想使用准备好的语句,因为它们有助于防止 SQL 注入(inject)。
A): 我可以将它分成两个后端调用,但当数据刷新时,前端的摘要会不同步。
B): 我可以将它们加入一个 MySQL 存储过程,然后在 PHP 中将它们分开,但我也需要将它们分开,所以相同的代码将是有两次。
C): 我可以停止使用准备好的语句,但我不知道还有什么其他方法可以避免 SQL 注入(inject)。
有什么建议吗?
最佳答案
好吧,我将尝试回答问题标题,假设在第一个语句中调用的不是常规查询,而是上述两个存储过程中的一个。
调用存储过程后,您总是必须移动每个存储过程返回的额外空结果集:
$mysqli->next_result();
此外,在第一次准备函数调用后,在获取数据后添加一个额外的 fetch():
$stmt->fetch();
$stmt->free_result();
因为您必须“释放”在服务器端等待的结果集。可以通过多种方式完成,但最简单的方法就是再调用一次 fetch(),或者更严格地说,您必须调用 fetch() 直到它返回 FALSE,表示结果集中不再有行.当在 while
循环中调用 fetch()
时,您在其他代码段中 [静默] 执行此操作,但在这里,只获取一行,您必须显式调用它.
还有另一种方法,方法更方便:使用 get_result()
(如果可用)它可以一次性解决所有问题。而不是你现在拥有的那些冗长而冗长的代码,实际上只需要四行:
$stmt = $mysqli->prepare('CALL getWeeksSummary(?,?,?)');
$stmt->bind_param('sss', $a, $b, $c);
$stmt->execute();
$weeksSummary = $stmt->get_result()->fetch_object();
get_result()
将释放等待的结果集,同时允许您使用 fetch_object()
方法,这将使您仅需获取结果对象一行。
关于php - 2 个准备好的语句,2 个存储过程,1 个 mysqli 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32773694/
创建一个“海盗对话”,可以选择左手或右手。我希望它对“左”和“右”的不同拼写做出积极的回答(正如您将在代码中看到的那样),但是,当我为所有非“右”或“左”的输入添加最终的“else”代码时,它给了我一
With 语句 对一个对象执行一系列的语句。 With object statements End With 参数 object 必需的部分
While...Wend 语句 当指定的条件为 True 时,执行一系列的语句。 While condition  ; Version [stat
所以我正在处理的代码有一个小问题。 while True: r = input("Line: ") n = r.split() if r == " ":
我有一个对象数组: var contacts = [ { "firstName": "Akira", "lastName": "Laine", "number"
int main() { int f=fun(); ... } int fun() { return 1; return 2; } 在上面的程序中,当从main函数中调用一个
我的项目中有很多 if 语句、嵌套 if 语句和 if-else 语句,我正在考虑将它们更改为 switch 语句。其中一些将具有嵌套的 switch 语句。我知道就编译而言,switch 语句通常更
Rem 语句 包含程序中的解释性注释。 Rem comment 或 ' comment comment 参数是需要包含的注释文本。在 Rem 关键字和 comment 之间应有一个空格。
ReDim 语句 在过程级中声明动态数组变量并分配或重新分配存储空间。 ReDim [Preserve] varname(subscripts) [, varname(subscripts)]
Randomize 语句 初始化随机数生成器。 Randomize [number] number 参数可以是任何有效的数值表达式。 说明 Randomize 使用 number 参数初始
Public 语句 定义公有变量并分配存储空间。在 Class 块中定义私有变量。 Public varname[([subscripts])][, varname[([subscripts])
Sub 语句 声明 Sub 过程的名称、参数以及构成其主体的代码。 [Public [Default]| Private] Sub name [( arglist )]
Set 语句 将对象引用赋给一个variable或property,或者将对象引用与事件关联。 Set objectvar = {objectexpression | New classname
我有这个代码块,有时第一个 if 语句先运行,有时第二个 if 语句先运行。我不确定为什么会这样,因为我认为 javascript 是同步的。 for (let i = 0; i < dataObje
这是一个 javascript 代码,我想把它写成这样:如果此人回答是,则回复“那很酷”,如果此人回答否,则回复“我会让你开心”,如果此人回答的问题包含"is"或“否”,请说“仅键入”是或否,没有任何
这是我的任务,我尝试仅使用简短的 if 语句来完成此任务,我得到的唯一错误是使用“(0.5<=ratio<2 )”,除此之外,构造正确吗? Scanner scn = new Scanner(
有没有办法在 select 语句中使用 if 语句? 我不能在这个中使用 Case 语句。实际上我正在使用 iReport 并且我有一个参数。我想要做的是,如果用户没有输入某个参数,它将选择所有实例。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: If vs. Switch Speed 我将以 C++ 为例,但我要问的问题不是针对特定语言的。我的意思是一
Property Set 语句 在 Class 块中,声明名称、参数和代码,这些构成了将引用设置到对象的 Property 过程的主体。 [Public | Private] Pro
Property Let 语句 在 Class 块中,声明名称、参数和代码等,它们构成了赋值(设置)的 Property 过程的主体。 [Public | Private] Prop
我是一名优秀的程序员,十分优秀!