CodeIgniter4 執(zhí)行查詢

2020-08-17 16:09 更新

基礎查詢

執(zhí)行常規(guī)查詢

使用 query 方法提交一個查詢:

$db->query('YOUR QUERY HERE');

執(zhí)行 “讀取” 類型查詢時,query() 方法返回一個數據庫查詢結果 對象 , 如何使用參考 顯示查詢結果 ;執(zhí)行 “寫入” 類查詢時, 只返回 TRUE 或 FALSE ,表示執(zhí)行成功或失敗。檢索數據時,你通常需要自行 編寫查詢語句,例如:

$query = $db->query('YOUR QUERY HERE');

執(zhí)行簡單查詢

simpleQuery 方法是 $db->query() 的簡化版本。它不會返回查詢結果, 不記錄查詢耗時,不會綁定變量,也不保存查詢語句(用于調試)。它只是簡單的 讓你執(zhí)行一個查詢語句,可能大多數用戶鮮有使用。

它只返回 “execute” 方法執(zhí)行的返回值,無關數據庫類型。 典型的返回值是 TRUE/FALSE ,當執(zhí)行類型是寫入型時,它表示寫操作的成功或失?。?插入、刪除或修改,實際就如此使用);執(zhí)行讀取類型時,表示能否成功獲取查詢結果資源/對象。

if ($db->simpleQuery('YOUR QUERY'))
{
        echo "Success!";
}
else
{
        echo "Query failed!";
}

注解

PostgreSQL的 pg_exec() 方法 (舉例) 執(zhí)行成功時 總是返回一個資源值,即使執(zhí)行寫入型查詢也是如此。 所以當你判斷布爾值時要切記此點。

手動指定數據表前綴

當你配置了數據庫的表前綴,執(zhí)行原生SQL查詢等類似操作,應當給數據表增加前綴, 你可以使用如下操作:

$db->prefixTable('tablename'); // 輸出 prefix_tablename

出于某些原因,你想以編程的方式修改表前綴,且不想創(chuàng)建新數據庫連接時,可以這樣做:

$db->setPrefix('newprefix');
$db->prefixTable('tablename'); // 輸出 newprefix_tablename

你可以用此方法隨時隨地獲取當前的表前綴:

$DBPrefix = $db->getPrefix();

保護標識符

許多數據庫建議保護表名和字段名 - 比如 MySQL 使用反引號。 查詢構造器會自動保護它們, 但如果你需要手動保護標識符時,可以這么做:

$db->protectIdentifiers('table_name');

重要

盡管查詢構造器會盡可能且適當的引用你所需的字段名和表名, 但請注意它不適用于惡意用戶輸入,勿將其用于未處理的用戶數據。

當你在數據庫配置文件里配有表前綴,這個方法還能給表加上前綴, 開啟這個功能請在第二個參數填寫 TRUE(布爾值):

$db->protectIdentifiers('table_name', TRUE);

查詢轉義

執(zhí)行數據庫查詢前做數據轉義是又好又安全的實踐,CodeIgniter 有三種方法幫到你:

1.$db->escape() 這個方法會判斷數據類型,對字符串數據做轉義, 它也會自動給數據加單引號,你無需額外處理:

$sql = "INSERT INTO table (title) VALUES(".$db->escape($title).")";

2.$db->escapeString() 這個方法對傳入數據做強制轉義,且無關類型, 多數時候你會用上面的方法而非這個。此方法使用舉例:

$sql = "INSERT INTO table (title) VALUES('".$db->escapeString($title)."')";

3.$db->escapeLikeString() 這個方法用于 LIKE 條件字符串轉義,

以確保 LIKE 的通配符 (‘%’, ‘_’) 也能正確的轉義。

$search = '20% raise';
$sql = "SELECT id FROM table WHERE column LIKE '%" .
$db->escapeLikeString($search)."%' ESCAPE '!'";

重要

escapeLikeString() 方法使用 ‘!’ (感嘆號) 轉義 LIKE 條件中的特殊字符,因為這個方法只轉義引號里的字符串, 它不能自動添加 ESCAPE '!' 條件,因此你必須手動添加。

查詢綁定

綁定可以讓你用簡單的查詢語法,讓系統(tǒng)將查詢語句合在一起,考慮下這個例子:

$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$db->query($sql, [3, 'live', 'Rick']);

查詢語句的問號會被方法第二個參數的數組順次替換。

使用IN條件時,綁定用多維數組搞定集合:

$sql = "SELECT * FROM some_table WHERE id IN ? AND status = ? AND author = ?";
$db->query($sql, [[3, 6], 'live', 'Rick']);

轉化后的語句是:

SELECT * FROM some_table WHERE id IN (3,6) AND status = 'live' AND author = 'Rick'

使用綁定的第二個好處是,它會自動轉義輸入值,生成安全的查詢語句。 你無需記住要手動轉義數據這件事 - 引擎會自動幫你完成。

命名綁定

你可以用命名綁定,而不用問號標記綁定值的位置,從而允許在查詢中使用鍵名匹配占位符:

$sql = "SELECT * FROM some_table WHERE id = :id: AND status = :status: AND author = :name:";
$db->query($sql, [
        'id'     => 3,
        'status' => 'live',
        'name'   => 'Rick'
]);

注解

查詢語句中的每個鍵名前后【必須】加英文冒號。

錯誤處理

$db->error();

如果你需要獲取最近一次發(fā)生的數據庫報錯,error() 方法會返回一個數組, 包含錯誤號和錯誤信息,來看下用例:

if ( ! $db->simpleQuery('SELECT `example_field` FROM `example_table`'))
{
        $error = $db->error(); // Has keys 'code' and 'message'
}

預編譯查詢

大部分數據庫引擎支持某種形式的預編譯語句,使你僅做一次預編譯,然后在新數據集上多次查詢。它消除了 SQL 注入的可能性,因為數據是以另一種形式傳給數據庫而非查詢語句。 當你需要多次執(zhí)行相同查詢時,它也相當快速。然而,若你想應用于所有查詢,這會極大影響性能,因為它通常要訪問數據庫兩次。 由于查詢構造器和數據庫連接已經處理了轉義數據,所以,安全方面已經為你解決了,但有時候,你也需要通過預編譯語句或預編譯查詢來優(yōu)化查詢。

編譯查詢語句

使用 prepare() 方法可輕松完成編譯,它有一個參數,是函數閉包,返回一個查詢對象。 查詢對象由任一 “最終” 類型的查詢自動生成,包括 insert , update , delete , replaceget 。使用查詢構造器執(zhí)行查詢可以最輕松地處理此問題。 查詢實際沒有執(zhí)行,傳入的值不重要也不會被處理,僅做占位使用。 這樣會返回一個預編譯查詢對象:

$pQuery = $db->prepare(function($db)
{
    return $db->table('user')
               ->insert([
                    'name'    => 'x',
                    'email'   => 'y',
                    'country' => 'US'
               ]);
});

如果你不想使用查詢構造器,你可以手動創(chuàng)建查詢對象,用問號做占位符:

use CodeIgniter\Database\Query;


$pQuery = $db->prepare(function($db)
{
    $sql = "INSERT INTO user (name, email, country) VALUES (?, ?, ?)";


    return (new Query($db))->setQuery($sql);
});

如果數據庫要求在預編譯階段提供選項數組,可以將數組放到第二個參數:

use CodeIgniter\Database\Query;


$pQuery = $db->prepare(function($db)
{
    $sql = "INSERT INTO user (name, email, country) VALUES (?, ?, ?)";


    return (new Query($db))->setQuery($sql);
}, $options);

執(zhí)行預編譯查詢

一旦你有了一個預編譯查詢,你可以使用 execute() 方法真正的執(zhí)行查詢。 你可以傳遞多個你需要的查詢參數,參數的個數必須與占位符個數相同,參數的順序也要與原始占位符保持一致:

// 編譯查詢語句
$pQuery = $db->prepare(function($db)
{
    return $db->table('user')
               ->insert([
                    'name'    => 'x',
                    'email'   => 'y',
                    'country' => 'US'
               ]);
});


// 準備數據
$name    = 'John Doe';
$email   = 'j.doe@example.com';
$country = 'US';


// 執(zhí)行查詢
$results = $pQuery->execute($name, $email, $country);

這會返回標準的 結果集.

其他方法

除了上述兩個主要方法,預編譯查詢還有以下方法可用:

close()

雖然 PHP 在(自動)關閉所有打開的查詢資源時做的非常好,但手動關閉執(zhí)行完的預編譯查詢同樣也是好的主意:

$pQuery->close();

getQueryString()

返回預編譯查詢的字符串。

hasError()

返回布爾值 true/false ,表示調用最近一次是否有執(zhí)行錯誤。

getErrorCode() getErrorMessage()

如果有報錯,可以用這兩個方法獲取錯誤號和錯誤信息。

使用查詢對象

在內部,所有查詢的處理和存儲都在 CodeIgniterDatabaseQuery 的實例中進行。 這個類負責綁定參數、也做預編譯查詢、還能保存查詢時的性能數據。

getLastQuery()

當你需要獲取最近一次的查詢對象,請使用 getLastQuery() 方法:

$query = $db->getLastQuery();
echo (string)$query;

查詢類

每個查詢對象都保存了此次查詢的一些信息,它有部分被時間線功能使用, 但你也可以使用(譯者注:此處時間線指數據庫執(zhí)行SQL過程,記錄它們方便調試和優(yōu)化性能)。

getQuery()

返回各種編譯構造之后的最終查詢語句,也就是發(fā)送到數據庫執(zhí)行的語句:

$sql = $query->getQuery();

將查詢對象做字符串轉換也能獲得相同的值:

$sql = (string)$query;

getOriginalQuery()

返回初始傳入對象里的 SQL 語句,沒有任何綁定或前綴修飾等等:

$sql = $query->getOriginalQuery();

hasError()

如果執(zhí)行時有任何錯誤,這個方法將返回 true:

if ($query->hasError())
{
        echo 'Code: '. $query->getErrorCode();
        echo 'Error: '. $query->getErrorMessage();
}

isWriteType()

如果當前查詢是寫入型 (例如 INSERT, UPDATE, DELETE, 等),此方法返回 true:

if ($query->isWriteType())
{
        ... do something
}

swapPrefix()

替換最終執(zhí)行的 SQL 里的表前綴,第一個參數是原始你想替換的前綴, 第二個參數是替換之后你想要的前綴:

$sql = $query->swapPrefix('ci3_', 'ci4_');

getStartTime()

獲取查詢執(zhí)行時間,以秒為單位,精確到毫秒級:

$microtime = $query->getStartTime();

getDuration()

返回執(zhí)行查詢的時長(秒),浮點數,精確到毫秒:

$microtime = $query->getDuration();
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號