iPhoneアプリ開発でSQLiteを使う必要があるので、概要を簡単にまとめてみます。
もっと詳しく知りたい方は、SQLite などを参考にしてください。
SQLデータベースの主な役割は、SQLステートメントに従って、データを扱うことです。この目的を達成するために、開発者は2つのことを知っておく必要があります。
目次
2つのオブジェクト
- データベース接続オブジェクト:sqlite3
- 準備ステートメント:sqlite3_stmt
sqlite3
typedef struct sqlite3 sqlite3;
各SQLiteデータベースは、”sqlite3″というポインタで表されます。sqlite3ポインタを一つのオブジェクトとして考えると便利です。
sqlite3_open(), sqlite3_open16(), sqlite3_open_v2() などは、そのコンストラクタです。そして、sqlite3_close() がデストラクタです。
sqlite3 には、他にもsqlite3_prepare_v2(),sqlite3_create_function(),sqlite3_busy_timeout() といった多くのメソッドがあります。
sqlite3_stmt
typedef struct sqlite3_stmt sqlite3_stmt;
このオブジェクトのインスタンスは、単一のSQLステートメントを表します。
このオブジェクトは、”準備ステートメント”、”コンパイルされたSQLステートメント”、または、単に、”ステートメント”として知られています。
このステートメントの動作は以下のような感じです。
6つのルーチン
- sqlite3_prepare_v2() や関連されたファンクションを使ってオブジェクトを生成
- sqlite3_prepare_v2() を使って主なパラメータと値を関連づけます
- sqlite3_step() を一度、または複数回呼び出してSQLを実行します
- sqlite3_reset() を使ってステートメントをリセットし、2番目のステップに戻ります
- qlite3_finalize() を使ってオブジェクトを破棄します
ここに登場した各メソッドの詳細はドキュメントを参照してください。
Objects, Constants, and Functions.
厳密にいえば、便利なラッパークラス(sqlite3_exec、sqlite3_get_table)が使え、「準備ステートメント:sqlite3_stmt」をカプセル化するので、必須ではありません。
「データベース接続オブジェクト:sqlite3」、「準備ステートメント:sqlite3_stmt」は、下記のC / C + +インタフェースルーチンの小さなセットによって制御されます。
上記の6つのルーチンと2つのオブジェクトがSQLiteの主な機能です。
これらを理解することが、SQLiteを利用する上で、とても重要です。
ただ、このルーチンリストは、概念的なものなので、実際には、複数のバージョンがあったり、同じことを実行するのに、異なる方法が存在したりすることに注意してください。
例)sqlite3_open(), sqlite3_open16() , sqlite3_open_v2()
また、sqlite3_column() と書いていますが、実際には、sqlite3_column()というものは存在しません。sqlite3_column()というのは、様々なデータ型の列データを抽出するために使用されるものの総称です。
主なインターフェースの概要
このルーチンは、SQLiteデータベースファイルへの接続し、「データベース接続オブジェクト」を返します。
これは、多くの場合、アプリケーションが行う、最初のSQLiteのAPIの呼び出しです。他のほとんどのSQLiteのAPIに必要なものです。
多くのSQLiteインターフェイスは、最初のパラメータとして「データベース接続オブジェクト」へのポインタを必要とするので、「データベース接続オブジェクト」のメソッドとして考えることができます。
このルーチンは、「データベース接続オブジェクト」のコンストラクタです。
このルーチンは、SQLテキストを「準備ステートメント」オブジェクトに変換し、そのオブジェクトへのポインタを返します。
このインターフェイスは、先に、sqlite3_open()によって作成された「データベース接続」のポインタと、SQLステートメントを含むテキスト文字列を必要とします。
このAPIは、実際には、SQL文を実行しません。単に実行のためのSQLステートメントを準備します。
sqlite3_prepareの使用は、推薦されていないことに注意してください。代替ルーチンsqlite3_prepare_v2()を代わりに使用する必要があります。
このルーチンは、前はsqlite3_prepare()のインターフェイスによって準備されたステートメントを実行するために使用されます。
このステートメントは、結果の最初の行が有効な限り、実行されます。
結果の2番目の行に進み、再度sqlite3_stepを実行します。
ステートメントが完了するまでsqlite3_step()を繰り返し呼び出します。
結果が返されないステートメント(例:INSERT、UPDATE、またはDELETE)は、sqlite3_step()の単一の呼び出しで完了します。
このルーチンは、sqlite3_step()で実行された「準備されたステートメント」への結果セットの現在の行から、単一カラムを返します。
sqlite3_step()は、新しい結果セットの行ごとに停止し、このルーチンは、その行のすべてのカラムの値を見つけるために複数回呼び出されます。
上述したように、SQLiteのAPIで”sqlite3_column()”関数というものはありません。いわゆる”sqlite3_column()”は、様々なデータ型の結果セットから値を返す関数の全体を表す総称です。
具体的には、戻り値によって以下のようなものが含まれています。
このルーチンは、sqlite3_prepare() で呼び出された「準備ステートメント」を破棄します。
メモリリークを回避するために、このルーチンの呼び出しを使用して、すべての「準備ステートメント」を破棄する必要があります。
このルーチンは、sqlite3_open() への呼び出しによって開かれたデータベース接続を閉じます。この接続に関連付けられているすべての「準備ステートメント」は、接続を閉じる前に確定されるべきである。
主要なオブジェクト&ルーチンの一般的な使い方
SQLite を使うアプリケーションは、通常、sqlite3_open() を使い、初期化中に、単一のデータベース接続を確立します。sqlite3_open() は、既存のデータベースに接続する際にも、新規データベースを作成する際にも使われます。
多くのアプリケーションは、単一のデータベース接続を使用していますが、同じデータベース、または異なったデータベースに関わらず、複数のデータベース接続が呼び出せないわけではありません。
時々、複合的なアプリケーションで、各スレッドに異なった「データベース接続」を作成しているものがありますが、複数のデータベースに接続するのに、異なった「データベース接続」を使う必要はありません。
ATTACH SQL コマンドを使うことで、単一の「データベース接続」で複数のデータベースに接続することが可能です。
多くのアプリケーションは、「データベース接続」を破棄するのに、sqlite3_close() を使っています。
SQLステートメントは、以下の流れで実行します。
- sqlite3_prepare() を使い、「準備ステートメント」を作成します
- sqlite3_step() を一度、または何度か、実行することにより、「準備ステートメント」を実行します
- sqlite3_column() で結果を取り出します
- sqlite3_finalize() で「準備ステートメント」を破棄します
その他には、もっと細かく利用する場合に役立つものがありますが、上記が、SQLiteを効果的に使うために最低限知っておくべきことです。
コアルーチン周りの便利なラッパー
sqlite3_exec() は、インターフェイスの1つの関数呼び出しで、上記の手順4つのすべてを行う便利なラッパーです。
sqlite3_exec() に渡されるコールバック関数は結果セットの各行を処理するために使用されています。
sqlite3_get_table() は、上記の手順のすべての4つを行う別の便利なラッパーです。
sqlite3_get_table()は、コールバックを呼び出すよりもヒープメモリ内のクエリの結果を格納するという点で、sqlite3_exec()とは異なります。
パラメータのバインドと準備ステートメントを再利用する
これまでの説明で、一旦、準備されたSQLは、実行され、破棄されると仮定しましたが、SQLiteは、同じ「準備ステートメント」を複数回実行することも可能です。
以下のようなルーチンを使うことで実現出来ます。
「準備ステートメント」は、sqlite3_step()の1つまたは複数の呼び出しによって実行された後、再度実行するために、sqlite3_reset() によりリセットされます。
既存の「準備ステートメント」にsqlite3_reset() を使うことで、不要な新しい「準備ステートメント」を作成することを避けることが出来ます。
多くのSQL文では、sqlite3_prepare() の実行回数が、sqlite3_step() の実行回数に等しいか超えることになりますので、sqlite3_prepare() の呼び出しを避けることがパフォーマンスの大幅な改善につながります。
一般的に、同じSQL文を何度も実行することは、懸命ではありません。例えば、異なった値を何度もINSERTしたい場合など、同じ「準備ステートメント」で値をセットすることが出来ます。
SQLite では、以下のようなパラメータを使うことで、実現出来ます。
- ?
- ?NNN
- :AAA
- $AAA
- @AAA
上記で例にあげた、NNN はinteger 型の値で、AAA は識別子です。パラメータの初期値はNULLです。
sqlite3_step() が最初に呼ばれる前に、または、sqlite3_reset() の直後に、アプリケーションは、パラメータに値を設置するために、sqlite3_bind() を実行します。sqlite3_bind() は呼ばれるたびに、同じパラメータの値がオーバーライドされます。
アプリケーションは、事前に複数のSQLステートメントを準備し、必要に応じてそれらを実行することが可能です。「準備ステートメント」の数には任意の制限はありません。
SQLite の拡張
SQLite は、以下のような機能拡張のインターフェースを含んでいます。
より詳しく知りたい方は、こちらなどでご確認ください。