PHP Conference Japan 2024

mysqli::query

mysqli_query

(PHP 5, PHP 7, PHP 8)

mysqli::query -- mysqli_query对数据库执行查询

描述

面向对象风格

public mysqli::query(string $query, int $result_mode = MYSQLI_STORE_RESULT): mysqli_result|bool

过程化风格

mysqli_query(mysqli $mysql, string $query, int $result_mode = MYSQLI_STORE_RESULT): mysqli_result|bool

对数据库执行 query

警告

安全警告:SQL 注入

如果查询包含任何变量输入,则应改用 参数化预处理语句。或者,数据必须被正确格式化,并且所有字符串都必须使用 mysqli_real_escape_string() 函数进行转义。

对于非 DML 查询(非 INSERT、UPDATE 或 DELETE),此函数类似于调用 mysqli_real_query(),然后调用 mysqli_use_result()mysqli_store_result()

注意:

在将长度超过服务器 max_allowed_packet 的语句传递给 mysqli_query() 的情况下,返回的错误代码根据您是否使用 MySQL Native Driver (mysqlnd) 或 MySQL Client Library (libmysqlclient) 而有所不同。行为如下

  • mysqlnd 在 Linux 上返回错误代码 1153。错误消息表示 获取到的数据包大于 max_allowed_packet 字节

  • mysqlnd 在 Windows 上返回错误代码 2006。此错误消息表示 服务器已断开连接

  • libmysqlclient 在所有平台上都返回错误代码 2006。此错误消息表示 服务器已断开连接

参数

mysql

仅过程化风格:由 mysqli_connect()mysqli_init() 返回的 mysqli 对象

query

查询字符串。

result_mode

结果模式可以是 3 个常量之一,指示 MySQL 服务器将如何返回结果。

MYSQLI_STORE_RESULT(默认) - 返回一个包含缓冲结果集的 mysqli_result 对象。

MYSQLI_USE_RESULT - 返回一个包含非缓冲结果集的 mysqli_result 对象。只要有待提取的挂起记录,连接线就会处于繁忙状态,并且所有后续调用都将返回错误 Commands out of sync。为了避免错误,必须从服务器提取所有记录,或者通过调用 mysqli_free_result() 丢弃结果集。

MYSQLI_ASYNC(可在 mysqlnd 中使用) - 查询异步执行,并且不会立即返回结果集。mysqli_poll() 然后用于从此类查询中获取结果。与 MYSQLI_STORE_RESULTMYSQLI_USE_RESULT 常量结合使用。

返回值

失败时返回 false。对于产生结果集的成功查询,例如 SELECT, SHOW, DESCRIBEEXPLAINmysqli_query() 将返回一个 mysqli_result 对象。对于其他成功查询,mysqli_query() 将返回 true

错误/异常

如果启用了 mysqli 错误报告 (MYSQLI_REPORT_ERROR) 并且请求的操作失败,则会生成警告。此外,如果模式设置为 MYSQLI_REPORT_STRICT,则会抛出 mysqli_sql_exception

示例

示例 #1 mysqli::query() 示例

面向对象风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* 创建表不返回结果集 */
$mysqli->query("CREATE TEMPORARY TABLE myCity LIKE City");
printf("Table myCity successfully created.\n");

/* 选择查询返回结果集 */
$result = $mysqli->query("SELECT Name FROM City LIMIT 10");
printf("Select returned %d rows.\n", $result->num_rows);

/* 如果我们必须检索大量数据,我们使用 MYSQLI_USE_RESULT */
$result = $mysqli->query("SELECT * FROM City", MYSQLI_USE_RESULT);

/* 注意,在所有记录完全检索或结果集关闭之前,我们无法执行任何与服务器交互的函数。
所有调用都将返回“不同步”错误 */
$mysqli->query("SET @a:='this will not work'");

过程化风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* 创建表不返回结果集 */
mysqli_query($link, "CREATE TEMPORARY TABLE myCity LIKE City");
printf("Table myCity successfully created.\n");

/* 选择查询返回结果集 */
$result = mysqli_query($link, "SELECT Name FROM City LIMIT 10");
printf("Select returned %d rows.\n", mysqli_num_rows($result));

/* 如果我们需要检索大量数据,我们使用 MYSQLI_USE_RESULT */
$result = mysqli_query($link, "SELECT * FROM City", MYSQLI_USE_RESULT);

/* 注意,在我们检索完所有记录或关闭结果集之前,我们不能执行任何与服务器交互的函数。
所有调用都将返回“不同步”错误 */
mysqli_query($link, "SET @a:='this will not work'");

以上示例将输出类似以下内容

Table myCity successfully created.
Select returned 10 rows.

Fatal error: Uncaught mysqli_sql_exception: Commands out of sync; you can't run this command now in...

参见

添加注释

用户贡献的注释 8 条注释

51
NUNTIUS
16 年前
这对于某些人来说可能显而易见,也可能不明显,但也许它可以帮助某些人。

在运行 SQL 中的联接时,如果您尝试提取两个名称相同的列,可能会遇到问题。mysqli 在按名称调用时返回查询中的最后一个。因此,要获取所需内容,您可以使用别名。

在下面,我尝试将用户 ID 与用户角色联接起来。在第一个表 (tbl_usr) 中,角色是一个数字,在第二个表中是一个文本名称 (tbl_memrole 是一个查找表)。如果我将它们都称为角色,我将获得文本,因为它是查询中的最后一个“角色”。如果我使用别名,那么我将获得两者,如以下所示。

<?php
$sql
= "SELECT a.uid, a.role AS roleid, b.role,
FROM tbl_usr a
INNER JOIN tbl_memrole b
ON a.role = b.id
"
;

if (
$result = $mysqli->query($sql)) {
while(
$obj = $result->fetch_object()){
$line.=$obj->uid;
$line.=$obj->role;
$line.=$obj->roleid;
}
}
$result->close();
unset(
$obj);
unset(
$sql);
unset(
$query);

?>
在这种情况下,我想我本可以重命名第一个表中的角色列为 roleid,这样就可以解决问题,但这是一种学习经验。
36
theyranos at gmail dot com
13 年前
神秘的“无法获取 mysqli”错误消息可能意味着许多事情,包括

1. 您正在尝试使用已关闭的数据库对象(如 ceo at l-i-e dot com 所述)。重新打开数据库连接,或找到对 <?php mysqli_close($db); ?><?php $db->close(); ?> 的调用并将其删除。
2. 您的 MySQLi 对象由于某种原因被序列化和反序列化。定义一个唤醒函数来重新创建您的数据库连接。 https://php.net/__wakeup
3. 除您之外的其他东西关闭了您的 mysqli 连接(特别是,请参阅 http://bugs.php.net/bug.php?id=33772)
4. 您混合使用了面向对象和函数式对数据库对象的调用。(因此,您在同一个程序中使用了 <?php $db->query() ?><?php mysqli_query($db) ?>)。
35
petrus.jvr
13 年前
在调用多个存储过程时,可能会遇到以下错误:“命令不同步;您现在无法运行此命令”。
即使在调用之间对结果对象使用 close() 函数,也会发生这种情况。
要解决此问题,请记住在每次存储过程调用后对 mysqli 对象调用 next_result() 函数。请参阅以下示例

<?php
// 新连接
$db = new mysqli('localhost','user','pass','database');

// 检查错误
if(mysqli_connect_errno()){
echo
mysqli_connect_error();
}

// 第 1 个查询
$result = $db->query("call getUsers()");
if(
$result){
// 循环遍历结果
while ($row = $result->fetch_object()){
$user_arr[] = $row;
}
// 释放结果集
$result->close();
$db->next_result();
}

// 第 2 个查询
$result = $db->query("call getGroups()");
if(
$result){
// 循环遍历结果
while ($row = $result->fetch_object()){
$group_arr[] = $row;
}
// 释放结果集
$result->close();
$db->next_result();
}
else echo(
$db->error);

// 关闭连接
$db->close();
?>
5
xa at sagexa dot com
2 年前
"在 PHP 8.1 中,MySQLi 扩展的默认错误处理行为已从静默错误更改为在错误时抛出异常。"
即使是 mysqli 的过程使用(即 mysqli_query)也是如此。
因此,使用 if(!mysqli_query($c, $sql)) [...] 是没有意义的。
要禁用异常抛出:mysqli_report(MYSQLI_REPORT_OFF);
9
匿名
6 年前
这是一个将查询结果干净地输出到 html 表格的示例

<table>
<tr>
<th>名</th>
<th>姓</th>
<th>城市</th>
</tr>
<?php while ($row = $myquery->fetch_assoc()) { ?>
<tr>
<td><?php echo $row["firstname"]; ?></td>
<td><?php echo $row["lastname"]; ?></td>
<td><?php echo $row["city"];?></td>
</tr>
<?php } ?>
</table>
0
Beeners
18 年前
存储过程。

使用 mysqli_query 调用返回结果集的存储过程。

这是一个简短的示例

<?php
$mysqli
= new mysqli(DBURI,DBUSER,DBPASS,DBNAME);
if (
mysqli_connect_errno())
{
printf("连接失败: %s\n", mysqli_connect_error());
exit();
}

$SQL = "CALL my_procedure($something)";
if ( (
$result = $mysqli->query($SQL))===false )
{
printf("无效查询: %s\n完整查询: %s\n", $mysqli->error, $SQL);
exit();
}

while (
$myrow = $result->fetch_array(MYSQLI_ASSOC))
{
$aValue[]=$myrow["a"];
$bValue[]=$myrow["b"];
}
$result->close();
$mysqli->close();
?>
希望这能为某些人节省一些时间。
-1
registrations at jdfoxmicro dot com
14年前
我喜欢将查询本身保存到日志文件中,这样我就不必担心网站是否处于活动状态。

例如,我可能有一个全局函数

<?php
function UpdateLog ( $string , $logfile ) {
$fh = fopen ( $logfile , 'a' );
$fwrite ( $fh , strftime ('%F %T %z')." ".$string."\n";
fclose ( $fh );
}
?>

然后在我的mysql函数错误捕获器中,类似于以下内容

<?php
$error_msg
= "数据库错误在 [page].php / ";
$error_msg .= mysqli_error ( $link )." / ";
$error_msg .= $query;
UpdateLog ( $error_msg , DB_ERROR_LOG_FILE );
?>

我还包括远程IP、用户代理等,但我将其从这些代码示例中删除了。并且在捕获错误时也让我收到电子邮件。

Jeff
-1
ceo at l-i-e dot com
16 年前
翻译
"无法获取mysqli"

您已关闭连接并尝试再次使用它。

我花了几天时间才弄清楚这条模糊的错误消息的含义……
To Top