MySQLi的擴充相對於PDO來說功能更加的豐富,所以我們還是會在學習過程中穿插各種MySQLi中好玩的方法函數。不過,今天的主角是MySQLi中如何執行SQL語句以及多條SQL語句的執行。
連結與選擇資料庫
首先是一個小內容的學習分享,還是連結資料庫,不過這次我們用另外一種方式來進行連結。
$mysqli = new mysqli(); $mysqli->real_connect("localhost", "root", "", "blog_test"); var_dump($mysqli); // ["thread_id"]=> // int(163) $mysqli->real_connect("localhost", "root2", "123", "blog_test"); var_dump($mysqli); // ["thread_id"]=> // int(164)
首先,我們實例化了一個 mysqli 物件。在實例化過程中,我們並沒有給 mysqli 的建構函式傳遞任何的參數,而是使用 real_connect() 方法來傳遞資料庫伺服器資訊並建立連線。
相信不少朋友從程式碼就可以看出,我們使用 real_connect() 可以在一個 mysqli 實例下來切換不同的資料庫連線。透過列印 mysqli 物件的內容就可以看出,兩個連接的線程ID不同,也就是說,它們是不同的兩個連接,但是使用的都是最上面所初始化的那個 mysqli 物件。
連線可以切換了,那我們要連接的資料庫呢?當然也可以方便切換。
$mysqli->select_db('mysql');
就是這樣一個簡單的 select_db() 方法,就可以幫助我們在程式碼執行過程中動態地修改所連接的資料庫。
執行SQL 語句
對PDO 來說,如果是查詢語句,我們需要使用query() 方法,如果是增、刪、改之類的其它語句,我們要使用exec() ,透過這兩個方法分別執行不同的SQL 語句。但在 MySQLi 中,我們統一隻使用 query() 方法就可以了。
$mysqli->query("insert into zyblog_test_user(username, password, salt) values('3a', '3a', '3a')"); var_dump($mysqli->affected_rows); var_dump($mysqli->insert_id); $mysqli->query("update zyblog_test_user set password='3aa' where username='3a'"); var_dump($mysqli->affected_rows); $mysqli->query("delete from zyblog_test_user where id = 60"); var_dump($mysqli->affected_rows); $res = $mysqli->query("select * from zyblog_test_user where username='3a'"); print_r($res); // mysqli_result Object // ( // [current_field] => 0 // [field_count] => 4 // [lengths] => // [num_rows] => 3 // [type] => 0 // ) print_r($res->fetch_assoc()); // Array // ( // [id] => 61 // [username] => 3a // [password] => 3aa // [salt] => 3a // ) while ($row = $res->fetch_assoc()) { print_r($row); } // Array // ( // [id] => 62 // [username] => 3a // [password] => 3aa // [salt] => 3a // ) // Array // ( // [id] => 63 // [username] => 3a // [password] => 3aa // [salt] => 3a // ) // ……
對於增、刪、改之類的語句,query() 方法只會傳回一個布林值,也就是語句是否執行成功。記住,它傳回的不是受影響的行數,這一點是需要注意的。我們如果需要取得受影響的行數需要使用 MySQLi 的屬性 affected_rows 。對於插入語句來說,取得最新插入的資料ID使用的是 insert_id 屬性。
如果執行的是 SELECT 語句,那麼 query() 傳回的就是一個 mysqli_result 對象,它代表從一個資料庫查詢中取得的結果集。關於這個物件的內容我們將在後面的文章中進行詳細的說明。
執行多條SQL 語句
執行多條SQL 語句的能力對於PDO 來說是無法實現的,不過據說PDO 是支援的,語句是可以正常執行的,但是我們拿不到完整的回傳結果。
$sql = "insert into zyblog_test_user(username, password, salt) values('3bb', '3bb', '3bb');" . "update zyblog_test_user set password='3aa' where username='3a';" . "select * from zyblog_test_user where username='3b';" . "select now()"; $pdo = new PDO("mysql:dns=locahost;dbname=blog_test", 'root', '', [PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]); $res = $pdo->exec($sql); var_dump($res); // int(1) $stmt = $pdo->query($sql); foreach ($stmt as $row) { //PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error in var_dump($row); }
從程式碼可以看出,如果使用的是 exec() 方法,那麼回傳的就是 INSERT 語句的結果。如果使用 query() 方法,則傳回的雖然是 PDOStatement 對象,但它是無法遍歷的。
接下來我們就來看看 MySQLi 是如何來執行這個多條語句拼接在一起的 SQL 語句的。
$mysqli->multi_query($sql); $i = 1; do{ echo '第' . $i . '条:', PHP_EOL; $i++; $result = $mysqli->use_result(); var_dump($result); var_dump($mysqli->affected_rows); if(is_object($result)){ var_dump($result->fetch_assoc()); } var_dump($mysqli->next_result()); echo '========', PHP_EOL; } while($mysqli->more_results() ); // 第1条: // bool(false) // int(1) // ======== // 第2条: // bool(false) // int(0) // ======== // 第3条: // object(mysqli_result)#2 (5) { // ["current_field"]=> // int(0) // ["field_count"]=> // int(4) // ["lengths"]=> // NULL // ["num_rows"]=> // int(0) // ["type"]=> // int(1) // } // int(-1) // array(4) { // ["id"]=> // string(2) "67" // ["username"]=> // string(2) "3b" // ["password"]=> // string(2) "3b" // ["salt"]=> // string(2) "3b" // } // ======== // 第4条: // bool(false) // int(0) // ========
multi_query() 就是 MySQLi 提供的執行多條 SQL 語句的方法。透過它執行之後,傳回的結果是一個布林值,如果第一個語句就有問題的話,那麼它傳回的就是 FALSE 。如果是後面的語句錯誤了,我們需要呼叫 next_result() 才能取得後面語句的錯誤訊息。
其實這也引出了我們 next_result() 這個方法的作用。它就相當於為執行取得下一個結果的操作做準備,也可以看作是將遊標移到了下一條 SQL 語句上。而 more_results() 方法就是判斷是否還有更多的語句沒有執行。
use_result
在上面的測試程式碼中,取得每一語句的執行結果使用的是 use_result() 這個方法。它的作用是啟動結果集的檢索。也就是說,在 mutli_query() 的時候,這些語句並沒有馬上執行,而是在呼叫 use_result() 時,才會執行目前的這條語句。我們注意到 INSERT 、 UPDATE 語句回傳的結果都是 FALSE 。而 SELECT 語句中的 num_rows 也是 0 。這就是它的特點,它也並沒有直接將結果集的資訊保存在程式的記憶體中。所以,use_result() 方法最大的好處就是佔用記憶體小,適合大量查詢的遍歷,缺點則是每次都要去資料庫查詢,速度慢。
store_result
除了 use_result() 之外,還有一個 store_result() 方法可以幫助我們得到查詢的結果集。它和 use_result() 方法是相反的,也就是說,它是直接執行就將結果集保存在記憶體中了。
$mysqli = new mysqli("localhost", "root", "", "blog_test"); $mysqli->multi_query($sql); $i = 1; do{ echo '第' . $i . '条:', PHP_EOL; $i++; $result = $mysqli->store_result(); var_dump($result); var_dump($mysqli->affected_rows); if(is_object($result)){ var_dump($result->fetch_assoc()); } var_dump($mysqli->next_result()); echo '========', PHP_EOL; } while($mysqli->more_results() ); // 第1条: // bool(false) // int(1) // ======== // 第2条: // bool(false) // int(0) // ======== // 第3条: // object(mysqli_result)#1 (5) { // ["current_field"]=> // int(0) // ["field_count"]=> // int(4) // ["lengths"]=> // NULL // ["num_rows"]=> // int(7) // ["type"]=> // int(0) // } // int(7) // array(4) { // ["id"]=> // string(2) "67" // ["username"]=> // string(2) "3b" // ["password"]=> // string(2) "3b" // ["salt"]=> // string(2) "3b" // } // ======== // 第4条: // object(mysqli_result)#3 (5) { // ["current_field"]=> // int(0) // ["field_count"]=> // int(1) // ["lengths"]=> // NULL // ["num_rows"]=> // int(1) // ["type"]=> // int(0) // } // int(1) // array(1) { // ["now()"]=> // string(19) "2020-09-14 10:31:37" // }
不只查詢結果中的 num_rows 有資料了,最後一條 SELECT now(); 語句也成功回傳了。它和我們日常使用 query() 的結果是類似的。
另外要注意的一點是,大家可以看一下我們執行這兩條取得結果方式的循環條件是如何寫得。 more_results() 和 next_result() 針對這兩種結果集的取得方式也是不同的,大家可以自己測一下。
总结
光说不练假把式,虽说多语句执行看似很美好,但即使在这简单的测试代码中,也会出现各种问题,大家一定要自己多尝试一下。在日常的开发过程中,最好还是一条一条的语句来执行,避免出现各种无法查明的问题而影响我们正常的业务执行。至于到底要不要使用这个能力,还是大家仁者见仁智者见智了。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202009/source/6.PHP中的MySQLi扩展学习(三)mysqli的基本操作.php
推荐学习:php视频教程
以上是PHP中mysqli的基本操作有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文比較了酸和基本數據庫模型,詳細介紹了它們的特徵和適當的用例。酸優先確定數據完整性和一致性,適合財務和電子商務應用程序,而基礎則側重於可用性和

本文討論了確保PHP文件上傳的確保,以防止諸如代碼注入之類的漏洞。它專注於文件類型驗證,安全存儲和錯誤處理以增強應用程序安全性。

本文討論了在PHP中實施API速率限制的策略,包括諸如令牌桶和漏水桶等算法,以及使用Symfony/Rate-limimiter之類的庫。它還涵蓋監視,動態調整速率限制和手

本文討論了使用password_hash和pyspasswify在PHP中使用密碼的好處。主要論點是,這些功能通過自動鹽,強大的哈希算法和SECH來增強密碼保護

本文討論了OWASP在PHP和緩解策略中的十大漏洞。關鍵問題包括注射,驗證損壞和XSS,並提供用於監視和保護PHP應用程序的推薦工具。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

記事本++7.3.1
好用且免費的程式碼編輯器

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

Dreamweaver CS6
視覺化網頁開發工具