PHP 日本研討會 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()

注意:

如果傳遞給 mysqli_query() 的語句長度大於伺服器的 max_allowed_packet,則返回的錯誤碼會因您使用的是 MySQL Native Driver(mysqlnd)還是 MySQL Client Library(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、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("資料表 myCity 已成功建立。\n");

/* Select 查詢會回傳結果集 */
$result = $mysqli->query("SELECT Name FROM City LIMIT 10");
printf("Select 回傳 %d 列。\n", $result->num_rows);

/* 如果我們必須擷取大量資料,我們會使用 MYSQLI_USE_RESULT */
$result = $mysqli->query("SELECT * FROM City", MYSQLI_USE_RESULT);

/* 請注意,在完全擷取所有記錄或關閉結果集之前,我們無法執行任何與伺服器互動的函數。所有呼叫都會回傳「out of sync」錯誤 */
$mysqli->query("SET @a:='這個不會運作'");

程序樣式

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

/* Select 查詢會回傳結果集 */
$result = mysqli_query($link, "SELECT Name FROM City LIMIT 10");
printf("Select 回傳 %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...

另請參閱

新增註解

使用者貢獻的註解 8 則註解

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,這樣就可以解決問題,但這是一個學習的經驗。
theyranos at gmail dot com
13 年前
神秘的「Couldn't fetch mysqli」錯誤訊息可能表示許多事情,包括

1. 您嘗試使用您已關閉的資料庫物件(如 ceo at l-i-e dot com 所述)。重新開啟資料庫連線,或尋找對 <?php mysqli_close($db); ?><?php $db->close(); ?> 的呼叫並將其移除。
2. 您的 MySQLi 物件由於某種原因已被序列化和反序列化。定義一個喚醒函式以重新建立您的資料庫連線。 https://php.dev.org.tw/__wakeup
3. 除了您以外的其他東西關閉了您的 mysqli 連線(特別是,請參閱 http://bugs.php.net/bug.php?id=33772
4. 您混合了 OOP 和函式呼叫資料庫物件。(因此,您在同一個程式中同時有 <?php $db->query() ?><?php mysqli_query($db) ?>)。
petrus.jvr
13 年前
當呼叫多個預存程序時,您可能會遇到以下錯誤:「Commands out of sync; you can't run this command now」。
即使在呼叫之間於結果物件上使用 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
2 年前
「在 PHP 8.1 中,MySQLi 擴充功能的預設錯誤處理行為已從靜默錯誤變更為在錯誤時拋出例外。」
即使對於 mysqli 的程序式使用(即 mysqli_query)也是如此。
因此,使用 if(!mysqli_query($c, $sql)) [...] 是沒有意義的。
若要停用拋出例外:mysqli_report(MYSQLI_REPORT_OFF);
Anonymous
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>
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();
?>
希望這能幫到一些人節省時間。
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
ceo at l-i-e dot com
16 年前
翻譯
「無法取得 mysqli」

您關閉了連線,然後又嘗試再次使用它。

我花了數天的時間才弄清楚這個晦澀的錯誤訊息是什麼意思...
To Top