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()

注意:

如果传递给 mysqli_query() 的语句长度超过服务器的 max_allowed_packet,则返回的错误代码将根据您使用的是 MySQL 本机驱动程序 (mysqlnd) 还是 MySQL 客户端库 (libmysqlclient) 而有所不同。行为如下

  • Linux 上的 mysqlnd 返回错误代码 1153。错误消息表示 收到一个大于 max_allowed_packet 字节的包

  • Windows 上的 mysqlnd 返回错误代码 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, DESCRIBEEXPLAIN),mysqli_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);

/* 注意,在所有记录完全检索到或结果集关闭之前,我们无法执行任何与服务器交互的函数。
所有调用都会返回 'out of sync' 错误 */
$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("myCity 表创建成功。\n");

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

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

/* 注意,在我们检索完所有记录或关闭结果集之前,我们不能执行任何与服务器交互的函数。所有调用都将返回“out of sync”错误 */
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...

另请参阅

添加注释

用户贡献注释 21 个注释

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);

?>
在这种情况下,我想我可以重命名第一个表的 role 列为 roleid,这样就可以解决问题,但这是一种学习体验。
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. 您将 OOP 和函数式调用混合到数据库对象中。(因此,您在同一个程序中既有 <?php $db->query() ?> 也有 <?php mysqli_query($db) ?>)。
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();
?>
xa at sagexa dot com
1 年前
"在 PHP 8.1 中,MySQLi 扩展的默认错误处理行为已从静默错误更改为在错误时抛出异常。"。
即使对于 mysqli 的过程使用,即 mysqli_query,也是如此。
因此,使用 if(!mysqli_query($c, $sql)) [...] 是毫无意义的。
要禁用异常抛出:mysqli_report(MYSQLI_REPORT_OFF);
匿名
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>
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
= "Database error in [page].php / ";
$error_msg .= mysqli_error ( $link )." / ";
$error_msg .= $query;
UpdateLog ( $error_msg , DB_ERROR_LOG_FILE );
?>

我还包含了远程 IP、用户代理等,但我把它从这些代码示例中删除了。并且在捕获错误时也通过电子邮件发送给我。

杰夫
Beeners
18 年前
存储过程。

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

这是一个简短的例子

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

$SQL = "CALL my_procedure($something)";
if ( (
$result = $mysqli->query($SQL))===false )
{
printf("Invalid query: %s\nWhole query: %s\n", $mysqli->error, $SQL);
exit();
}

while (
$myrow = $result->fetch_array(MYSQLI_ASSOC))
{
$aValue[]=$myrow["a"];
$bValue[]=$myrow["b"];
}
$result->close();
$mysqli->close();
?>
我希望这能节省一些人的时间。
ceo at l-i-e dot com
15 年前
翻译
"无法获取 mysqli"

你关闭了连接并试图再次使用它。

我花了几天时间才弄明白这个模糊的错误信息意味着什么...
info at ff dot net
18 年前
调用存储过程

Beeners 的笔记/示例不起作用。使用 mysqli_multi_query() 调用存储过程。SP 具有第二个结果集,其中包含状态:'OK' 或 'ERR'。使用 mysqli_query 将不起作用,因为有多个结果。

<?php
$sQuery
="CALL SomeSP('params')";
if(!
mysqli_multi_query($sqlLink,$sQuery)) {
// your error handler
}
$sqlResult=mysqli_store_result($sqlLink);

if(
mysqli_more_results($this->sqlLink))//Catch 'OK'/'ERR'
while(mysqli_next_result($this->sqlLink));
?>

当然,您将不得不为其重写/扩展一些内容以获得更高的可用性,但这只是一个示例。
hunreal at gmail dot com
20 年前
使用不同的排序规则/字符进行连接、结果。
您可以在查询之前设置排序规则。

例如,想要将排序规则设置为 utf8_general_ci
您可以先发送查询“SET NAMES 'utf8'”

<?php
$mysqli
=new mysqli('localhost', 'root', 'password', 'test');
$mysqli->query("SET NAMES 'utf8'");
$q=$mysqli->query("select * from test");
while(
$r=$q->fetch_assoc()) {
print_r($r);
}
?>

关于字符设置有很多变量。
通过运行 sql 命令,SHOW VARIABLES LIKE 'char%';
有一些变量控制字符的使用。

character_set_client
character_set_connection
character_set_database
character_set_results
character_set_server
character_set_system

此外,SET NAMES 可以用一个或一些设置替换,例如 SET character_set_results='utf8';
jcwebb at dicoe dot com
17 年前
在构建应用程序时,我喜欢在失败时看到整个语句。
<?php
$q
="SELECT somecolumn FROM sometable"; //some instruction
$r=mysqli_query($DBlink,$q) or die(mysqli_error($DBlink)." Q=".$q);
?>
如果出现错误(比如我无数的打字错误),这将显示整个指令。
适合开发(在生产服务器上不太好 - 完成后只需查找和替换:$r=mysqli_query($DBlink,$q); )

希望对您有所帮助。乔恩
joseph_robert_martinez at yahoo dot com
10 年前
对于那些在服务器上启用了复制功能的人,在任何数据修改查询之前添加 mysqli_select_db() 语句。MySQL 复制不会以相同的方式处理带有 db.table 的语句,如果在之前没有选择模式,则不会复制到从服务器。

在另一个网站上重置主服务器和从服务器几天后才发现 http://www.linuxquestions.org/questions/linux-server-73/mysql-5-1-not-replicating-properly-with-slave-823296/
Igor
15 年前
mysqli::query() 只能执行一个 SQL 语句。

当您想在一个查询中运行多个 SQL 语句时,请使用 mysqli::multi_query()。
omidbahrami1990 at gmail dot com
6 年前
这是一个使用 mysqli::query 的安全方法
--------------------------------------------------------
<?php
function secured_query($sql)
{
$connection = new mysqli($host,$username,$password,$name);

if (
$connection->connect_error)
die(
"Secured");

$result=$connection->query($sql);
if(
$result==FALSE)
die(
"Secured");

$connection->close();
return
$result;
}
/*
$host ---> DataBase IP Address
$username ---> DataBase Username
$password ---> DataBase Password
$name ---> DataBase Name
*/
?>
ahmed dot 3abdolah at gmail dot com
9 年前
嗨,我创建了一个使用数组添加新表的函数,我在我的项目中使用它...
<?PHP
/* 此函数来自 PHP.net */
function array_keys_exist(&$key,array &$array){
$keys = split("\|",$key);
foreach(
$keys as $key_s){
if(
array_key_exists($key_s, $array)) return true;
}
return
false;
}
/* 这是我的函数 */
array_create_table(array &$array){
if(
is_array($array)){
$key = "table|rows|values";
$info = "";
if(
array_keys_exist($key,$array)){
if(
is_array($array["rows"]) and is_array($array["values"]) ){

if(
count($array["rows"]) == count($array["values"])) {
for(
$i=0; $i<=count($array["rows"]); $i++){
$info = $info." ".$array["rows"][$i]." ".$array["values"][$i]." NOT NULL ";
if(
$i < count($array["rows"])-1 ) $info = $info.",";
}
$query = "CREATE TABLE ".$this->private_tables_name.$array["table"]." ";
$query .= "( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, ".$info." )";
return
$query;
}
}
}else return
"Error";
}
}

/* 使用方法很简单 */
$database = new database(); // 连接到数据库,我使用的是 mysqli ...
$array = array("table"=>"MRO", "rows"=>array("name","username") , "values" => array("VARCHAR (50) "," VARCHAR (50) ") );

$query = array_create_table($array); // 转换并创建查询 ...
if($database->query($query)) echo "Work"; else echo "Error"; // 结果:work

?>
thomas dekker
13 年前
构建插入语句很麻烦。这个辅助函数使用键名作为列名将数组插入到表中。

<?php
private function store_array (&$data, $table, $mysqli)
{
$cols = implode(',', array_keys($data));
foreach (
array_values($data) as $value)
{
isset(
$vals) ? $vals .= ',' : $vals = '';
$vals .= '\''.$this->mysql->real_escape_string($value).'\'';
}
$mysqli->real_query('INSERT INTO '.$table.' ('.$cols.') VALUES ('.$vals.')');
}
?>

根据你的具体需求进行调整。
marcus at synchromedia dot co dot uk
13 年前
成功查询返回的具体类型是 mysqli_result。
popere dot noel at yahoo dot com
11 years ago
或者你可以直接扩展这个类...
在我的情况下,我已经有一个数据库包装器,所以类似这样就很容易了

public function free($result) {

$result->free_result();
$this->link->next_result();
}

试了一下,效果很好!
blinki bill, argodak at yahoo dot com
11 years ago
最近我在执行 DML 查询(特别是更新操作)时遇到了一个令人费解的问题,每次调用更新查询后,如果还有其他查询需要执行,就会在页面上出现这个错误,并记录到 error_log 中
"致命错误:在未知位置抛出异常,没有堆栈帧"

奇怪的是,所有查询都执行得很好,所以不太理解

$update = mysqli_query($connection, $query_string);
if(!$update){
echo 'Houston we have a problem '.mysqli_error($connection);
exit;
}

在上面的例子中,"$update" 为 "true",mysqli_error() 为空,当然更新操作也执行成功了,但是仍然出现了这个让人讨厌的超级神秘错误。
更让我不明白的是我的解决方法——在更新查询之后调用 "mysqli_free_result",问题就消失了。但是由于 "mysqli_free_result" 不应该在 DML 查询之后调用(释放什么,一个布尔值?哈哈),所以需要用 try catch 块将其包装起来。

try{
mysqli_free_result($update);
}catch (Exception $e){
//不做任何操作
}

所以,我不知道为什么,但似乎当 DML 查询负责时
"致命错误:在未知位置抛出异常,没有堆栈帧"
在查询之后调用 "mysqli_free_result" 似乎可以解决这个问题
Anonymous
7 years ago
我不知道这是个 bug 还是什么,先在这里记录一下。使用 MYSQLI_USE_RESULT 选项的 SHOW 查询不会显示 num_rows
<?php
SHOW TABLES LIKE
[some table], MYSQLI_USE_RESULT
num_rows
// 显示为 0!
?>
David Marcus
7 years ago
如果你使用的是 MYSQLI_STORE_RESULT 的默认结果模式,你可以在 $mysqli->query 之后以及使用 mysqli_result 之前调用 $mysqli->close()。这样可以减少连接打开的时间,如果数据库服务器对连接数有限制,这会很有帮助。
To Top