2024 日本 PHP 研討會

SQLite3Stmt::execute

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

SQLite3Stmt::execute執行預處理語句並返回結果集物件

說明

public SQLite3Stmt::execute(): SQLite3Result|false

執行已準備好的語句並返回結果集物件。

注意

透過在同一個語句物件上呼叫此方法檢索的結果集物件並非獨立的,而是共用相同的底層結構。因此,建議在再次於同一個語句物件上呼叫 SQLite3Stmt::execute() 之前,先呼叫 SQLite3Result::finalize()

參數

此函式沒有參數。

傳回值

成功執行準備好的語句時,返回一個 SQLite3Result 物件;失敗時,返回 false

另請參閱

新增註解

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

gmail@asmqb7
8 年前
目前 SQLite3 PHP 繫結(不是 SQLite3 本身)中存在一個問題,導致所有查詢都會執行兩次。顯然這個問題已經存在很長一段時間了。

更多資訊請參見:https://bugs.php.net/bug.php?id=64531

在發現上述問題之前,我發布了這個:http://stackoverflow.com/questions/36617708/odd-behavior-with-sqlite3-non-select-prepared-transactions-and-fetcharray(包含可複製貼上的錯誤示範)

解決方法:我強烈建議將任何可能在非 SELECT 查詢結果上運行 fetchArray() 的程式碼包裝在 numColumns() 檢查中,如下所示

<?php

$op
= $db->prepare(...);

$r = $op->execute(); // 查詢 #1

if ($r->numColumns()) { // 返回欄位數,這裡用作真/假測試
while ($row = $r->fetchArray(SQLITE3_ASSOC)) { // 查詢 #2
// 您的程式碼寫在這裡
}
}

?>

說明

- 查詢 #1 是 SQLite3 查詢第一次執行的地方,查詢 #2 是查詢再次執行的地方。是的,*所有*內容都會執行兩次;這就是錯誤所在。

- 如果您的程式碼只會讀取而不會修改資料庫(例如,不會導致修改資料庫的觸發器執行的 SELECT),那就沒問題。您的查詢會執行兩次,但不會改變結果。

- 如果您的程式碼會寫入資料庫 - 例如 INSERT - 如果欄位數為零,則**不得**執行 fetchArray()(並再次執行查詢)。

- 手冊中沒有記載,但在這裡 -https://php.dev.org.tw/manual/en/book.sqlite3.php#113144 - 用戶 'bohwaz' 提到自 PHP 5.3.11 起還有一個 SQLite3Stmt::readOnly() 函式,它會告訴您是否剛寫入資料庫。這目前沒有文件說明,但可能是比 numColumns() 更合適的替代方案(我不確定它的作用,它可能是一樣的)。

對於使用 SQLite3 的高負載工作,您可能會更喜歡 PDO。諷刺的是,這個綁定更輕量,並提供對一些 SQLite3 特定基元和行為的直接訪問……但它會執行所有查詢兩次。

[[給版主的說明(本節在閱讀後可以刪除;我也樂於接受以下內容的意見回饋)

- 請不要將此評論視為錯誤報告 - 我只是希望其他人也能意識到這個問題,這樣他們就不必花費數小時苦思冥想。 :P

- 截至此評論提交之日,此頁面有一個未批准的差異卡在 DocBook 中,因此我無法添加類似「由於錯誤 #64531,建議您將 fetchArray() 包裹在 numColumns() 中……」之類的內容,我認為在修復此錯誤之前,這比此評論更有份量。]]
macguru
7 年前
我成功地避免了預備語句多次執行,方法是在執行後使用 finalize() 處理結果。

$stmt->execute()->finalize();

希望這對其他人有幫助。
To Top