クエリ¶
クエリの基本¶
通常のクエリ¶
クエリを送信するには query メソッドを使います:
$db->query('ここにクエリを書く');
The query() function returns a database result object when "read" type queries are run which you can use to show your results. 「書き込み」タイプのクエリを実行したときは、成功失敗に従い単純に TRUE または FALSE を返します。クエリ結果を受け取るとき、変数に格納するには次のようにします:
$query = $db->query('クエリをここに書く');
単純化されたクエリ¶
simpleQuery メソッドは $db->query() メソッドを単純化したものです。データベース結果は 返 し ま せ ん 。クエリタイマも設定しません。データバインディングは処理します。デバッグのためにクエリを保存します。これはクエリ送信をシンプルにするためのものです。多くのユーザはこの機能を使うことはほとんどないでしょう。
この機能の返値はデータベースドライバの「execute」メソッドの返値です。 INSERT、DELETE、UPDATE のような書き込みタイプのクエリのとき(この機能はまさにそういう時に使うべきものです)、たいていは成功失敗の TRUE/FALSE を返します。結果をフェッチできるときは resource/object を返します。
if ($db->simpleQuery('クエリ'))
{
echo "成功!";
}
else
{
echo "クエリは失敗しました!";
}
注釈
PostgreSQL's pg_exec()
function (for example) always
returns a resource on success even for write type queries.
So keep that in mind if you're looking for a boolean value.
手動でのデータベースプレフィックスの操作¶
もしデータベースプレフィックスを設定していて、かつネイティブの SQL クエリにテーブル名を使用したい場合などでは、次のようにできます:
$db->prefixTable('tablename'); // prefix_tablename を返します
If for any reason you would like to change the prefix programmatically without needing to create a new connection you can use this method:
$db->setPrefix('newprefix');
$db->prefixTable('tablename'); // newprefix_tablename を返します
識別子の保護¶
In many databases, it is advisable to protect table and field names - for example with backticks in MySQL. Query Builder queries are automatically protected, but if you need to manually protect an identifier you can use:
$db->protectIdentifiers('table_name');
重要
Although the Query Builder will try its best to properly quote any field and table names that you feed it. Note that it is NOT designed to work with arbitrary user input. サニタイズされていないユーザデータを指定しては い け ま せ ん 。
データベース設定ファイルにプレフィックスを指定した場合、このメソッドはテーブル名にプレフィックスをつけることができます。プレフィックスを有効にしたい場合は第2引数に TRUE (boolean) を指定してください:
$db->protectIdentifiers('table_name', TRUE);
クエリのエスケープ¶
データベースに送信する前にデータをエスケープすることはセキュリティ上とても良い行いです。CodeIgniter にはそれをしてくれる3つのメソッドがあります:
$db->escape() このメソッドはデータ型を判定し、文字列の時だけエスケープします。また、自動的にシングルクォートをつけるので、手動で行う必要はありません:
$sql = "INSERT INTO table (title) VALUES(".$db->escape($title).")";
$db->escapeString() このメソッドはデータ型にかかわらず引数をエスケープします。多くの場合、このメソッドよりは前述のメソッドを使うことでしょう。このメソッドは次のように使います:
$sql = "INSERT INTO table (title) VALUES('".$db->escapeString($title)."')";
$db->escapeLikeString() このメソッドは LIKE 条件で使用する必要があるもので、LIKE のワイルドカード('%'、'_')を正しくエスケープします。
$search = '20% raise';
$sql = "SELECT id FROM table WHERE column LIKE '%" .
$db->escapeLikeString($search)."%' ESCAPE '!'";
重要
escapeLikeString()
メソッドは「!」(エクスクラメーション)を LIKE 条件のエスケープ文字として使用します。なぜならこのメソッドは部分文字列をエスケープしてそれをプログラマがクォートするでしょうから、 ESCAPE '!'
を自動的につけることができません。そのためプログラマが手動でやってやる必要があります。
クエリへのバインディング¶
バインディングはシステムでクエリをまとめ上げさせることで、プログラマが書くクエリの構文をシンプルにさせてくれます。次の例を考えてみましょう:
$sql = "SELECT * FROM some_table WHERE id = ?AND status = ?AND author = ?";
$db->query($sql, [3, 'live', 'Rick']);
クエリ内のクエスチョンマーク(?)は自動的に置換されます。置換する値は query メソッドの第2引数の配列で指定します。
バインドする値には配列も使用できます。 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'
The secondary benefit of using binds is that the values are automatically escaped producing safer queries. You don't have to remember to manually escape data — the engine does it automatically for you.
名前付きバインディング¶
値をバインディングする場所にクエスチョンマーク(?)を使うかわりに、プレースホルダとして配列のキーを名前に使うことができます:
$sql = "SELECT * FROM some_table WHERE id = :id: AND status = :status: AND author = :name:";
$db->query($sql, [
'id' => 3,
'status' => 'live',
'name' => 'Rick'
]);
注釈
Each name in the query MUST be surrounded by colons.
エラーハンドリング¶
$db->error();
If you need to get the last error that has occurred, the error() method will return an array containing its code and message. 簡単な例を示します:
if ( !$db->simpleQuery('SELECT `example_field` FROM `example_table`'))
{
$error = $db->error(); // 'code' と 'message' をキーに持ちます
}
プリペアドクエリ¶
ほとんどのデータベースエンジンは何らかの形でプリペアドステートメントをサポートします。いちどクエリを準備すれば、データを入れ替えて何度も実行できます。データはクエリそのものとは別の形で渡されるため、SQL インジェクションの可能性を排除できます。同じクエリを何度も実行する場合、ほんのちょっとですが速くもなります。しかしながら、データベースを2回以上呼び出すとき、すべてのクエリにプリペアドステートメントを使用することはパフォーマンス上意味のある効果が挙がりえます。クエリビルダとデータベース接続でデータのエスケープはハンドリングできますので、安全面はすでに考慮されています。しかし時には、プリペアドステートメントまたはプリペアドクエリを使うことでのクエリ最適化の余地が必要になることがあるでしょう。
クエリの準備¶
prepare()
メソッドを呼び出せばそれで準備ができます。引数は1つだけで、クエリオブジェクトを返すクロージャを指定します。クエリオブジェクトは「最終的な」形としてクエリを自動的に生成するもので、 insert 、 update 、 delete 、 replace 、そして get を含みます。クエリビルダを用いるのが一番簡単な処理方法です。The query is not actually run, and the values don't matter since they're never applied, acting instead
as placeholders. このメソッドは PreparedQuery オブジェクトを返します:
$pQuery = $db->prepare(function($db)
{
return $db->table('user')
->insert([
'name' => 'x',
'email' => 'y',
'country' => 'US'
]);
});
If you don't want to use the Query Builder you can create the Query object manually using question marks for value placeholders:
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(function($db)
{
$sql = "INSERT INTO user (name, email, country) VALUES (?, ?, ?)";
return (new Query($db))->setQuery($sql);
});
If the database requires an array of options passed to it during the prepare statement phase you can pass that array through in the second parameter:
use CodeIgniter\Database\Query;
$pQuery = $db->prepare(function($db)
{
$sql = "INSERT INTO user (name, email, country) VALUES (?, ?, ?)";
return (new Query($db))->setQuery($sql);
}, $options);
クエリの実行¶
Once you have a prepared query you can use the execute()
method to actually run the query. クエリに必要なだけの変数を渡してください。パラメータの数はクエリ内のプレースホルダの数と一致させなければなりません。また、クエリ内に現れるプレースホルダの順番とも一致させなければなりません。
// Prepare the Query $pQuery = $db->prepare(function($db) {
- return $db->table('user')
- ->insert([
- 'name' => 'x', 'email' => 'y', 'country' => 'US'
]);
});
// Collect the Data $name = 'John Doe'; $email = 'j.doe@example.com'; $country = 'US';
// Run the Query $results = $pQuery->execute($name, $email, $country);
これは標準の 結果セット を返します。
その他のメソッド¶
In addition to these two primary methods, the prepared query object also has the following methods:
close()
While PHP does a pretty good job of closing all open statements with the database it's always a good idea to close out the prepared statement when you're done with it:
$pQuery->close();
getQueryString()
これはプリペアドクエリを文字列として返します。
hasError()
最後に実行した execute() に何らかのエラーがなかったかどうか、真偽値 true/false を返します。
getErrorCode() getErrorMessage()
If any errors were encountered these methods can be used to retrieve the error code and string.
クエリオブジェクトの操作¶
内部的に、すべてのクエリは CodeIgniterDatabaseQuery のインスタンスとして処理され、保持されます。このクラスはパラメータのバインディングに責任を持ち、またそのクエリのパフォーマンスデータを保持します。
getLastQuery()
最後に実行したクエリオブジェクトが欲しいときには、 getLastQuery()メソッドを使います:
$query = $db->getLastQuery();
echo (string)$query;
クエリクラス¶
それぞれのクエリオブジェクトは、クエリに関するいくつかの部品となる情報を保持しています。 部分的にはタイムライン機能で使われますが、プログラマの用途にも使えます。
getQuery()
Returns the final query after all processing has happened. これはまさにデータベースに送信されたクエリそのものです:
$sql = $query->getQuery();
クエリオブジェクトを文字列にキャストしても同じ値を得られます:
$sql = (string)$query;
getOriginalQuery()
オブジェクトに渡された、加工前の SQL を返します。これには何もバインドされておらず、プレフィックスもついていませんし、その他についても同じです:
$sql = $query->getOriginalQuery();
hasError()
If an error was encountered during the execution of this query this method will return true:
if ($query->hasError())
{
echo 'エラーコード: '. $query->getErrorCode();
echo 'エラーメッセージ: '. $query->getErrorMessage();
}
isWriteType()
クエリが書き込みタイプであると判定された場合、true を返します(例: INSERT、UPDATE、 DELETE、など):
if ($query->isWriteType())
{
... 何かする
}
swapPrefix()
最終的な SQL で使用されるテーブル名プレフィックスを別の値に置き換えます。第1引数は置き換えたい元のプレフィックス、第2引数は置き換えたい先のプレフィックスです:
$sql = $query->swapPrefix('ci3_', 'ci4_');
getStartTime()
クエリの実行をした時刻をマイクロ秒で取得します:
$microtime = $query->getStartTime();
getDuration()
クエリにかかった時間を float 型でマイクロ秒で返します:
$microtime = $query->getDuration();