4.パラメータ設定
SQLにパラメータを渡すには、二つの方法があります。
1. SQL文を組み立てて、値を埋める
CString sql; sql.Format( _T("SELECT name FROM Names WHERE name = '%s'"), _T("Tom") );
CStringを使用するためUnicodeに対応するsqlite3_prepare16を使用します。
int rc = sqlite3_prepare16( db, sql, -1, &stmt );
この方法でSQL文を組立てる場合、SQLインジェクションという不正利用がおこる可能性がありますので、以下の方法2を推奨します。
2. SQLパラメータを使用する
上記方法1の’%s’のところを?で書き込みます。
int rc = sqlite3_prepare( db, "select name from names where name = ?", -1, &stmt );
そしてsqlite3_bindを使用して値を設定します。
値の型によって、以下の設定関数を使うことができます。
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); int sqlite3_bind_double(sqlite3_stmt*, int, double); int sqlite3_bind_int(sqlite3_stmt*, int, int); int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); int sqlite3_bind_null(sqlite3_stmt*, int); int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
使用例:
sqlite3_bind_text16( stmt, 1, _T("UNVELLソフトウェア"), SQLITE_STATIC );
5.その他
5.1. ONE STEPでデータベースを操作する
上記のように、データを取得する場合は、sqlite3_prepare
、sqlite3_step
、sqlite3_column
の三つの関数を使用する必要があります。
sqlite3_exec
関数を使用する場合は、上記3 STEPsの操作を1 STEPに削減できます。
sqlite3_exec
の定義は以下の通りです。
int sqlite3_exec( sqlite3*, /* データベースオブジェクト */ const char *sql, /* 実行するSQL */ int (*callback)(void*,int,char**,char**), /* コールバック関数 */ void *, /* コールバックに渡す引数 */ char **errmsg /* エラー情報 */ );
渡したSQLが実行されレコードが取得された後に、コールバック関数が呼び出されます。
その時に渡された一行のデータを処理します。
例:コールバック関数を定義します。
static int callback(void *NotUsed, int argc, char **argv, char **azColName) { int i; for (i=0; i < argc; i++) { printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); } printf("\n"); return 0; }
そしてSQLを実行します。
int rc = sqlite3_open( "test.db", &db ); char* zErrMsg = NULL; /* エラーメッセージへ指向ポインター */ rc = sqlite3_exec(db, "SELECT * FROM Names", callback, 0, &zErrMsg); /* エラーメッセージが返された場合はぜひ解放しましょう。 */ if( zErrMsg != NULL ) sqlite3_free( zErrMsg ); sqlite3_close(db);
5.2. 高速化&効率化
SQL文を変えずに、複数のデータを挿入したい場合は、 コンパイラステートメントを破棄せず、
一回コンパイラして 複数回使用したほうが高速化、効率化できます。
以下のパターン1で示した使い方ではなく、パターン2にしましょう。
パターン1: 誤×
int rc = sqlite3_open( "test.db", &db ); sqlite3_stmt* stmt; const TCHAR* szNames[] = { L"Bright", L"Owen", L"Alfred" }; for (int i = 0; i < _countof(szNames); i++) { sqlite3_prepare( db, "insert into Names ( name ) values (?)", -1, &stmt, NULL ); sqlite3_bind_text16( stmt, 1, szNames[i], -1, SQLITE_STATIC ); sqlite3_step( stmt ); sqlite3_finalize( stmt ); } sqlite3_close( db );
パターン2: 正○
int rc = sqlite3_open( "test.db", &db ); sqlite3_stmt* stmt; const TCHAR* szNames[] = { L"Bright", L"Owen", L"Alfred" }; rc = sqlite3_prepare( db, "INSERT INTO Names ( name ) VALUES ( ? )", -1, &stmt, NULL ); for (int i = 0; i < _countof(szNames); i++) { sqlite3_bind_text16( stmt, 1, szNames[i], -1, SQLITE_STATIC ); sqlite3_step( stmt ); sqlite3_reset( stmt ); } sqlite3_finalize( stmt ); sqlite3_close( db );
6.エラー処理
6.1. エラー検出
ほとんど全てのsqlite3関数はintタイプの戻りコードを返すので、それによって
エラーが発生したかどうかを判断できます。
int rc = sqlite3_...( ... ) if (rc != SQLITE_OK) { /* 最後のエラーメッセージを取得する */ AfxMessageBox( (LPCTSTR) sqlite3_errmsg16( db ) ); }
6.2. エラー処理
一般的にsqlite3_*関数のint型の戻り値を判断すると成功かエラーか判断できます。
例:
int rc = sqlite3_open("test.db", db); int rc = sqlite3_step(stmt); /* SQL実行する */
sqlite3_step
の場合、SQL操作によって以下の二つの戻り値が返されます。
INSERT,UPDATE,DELETE操作の場合 | SQLITE_DONE |
SELECT操作の場合 | SQLITE_ROW |
sqlite3_*
関数の戻り値以外には、以下のエラー処理に関係する関数が
用意されています。
int sqlite3_errcode(sqlite3 *db); | 最後のエラーコードを取得する |
int sqlite3_extended_errcode(sqlite3 *db); | 最後の拡張エラーコードを取得する。 |
const char *sqlite3_errmsg(sqlite3*); | 最後のエラーメッセージを取得する |
const void *sqlite3_errmsg16(sqlite3*); | 最後のUnicodeエラーメッセージを取得する(推奨) |
特に、日本語が含まれている場合があるので、sqlite3_errmsg16
の使用をお勧めします。
返却コード一覧表
成功系
定数 | 値 | 説明 |
SQLITE_OK | 0 | 成功 |
失敗系
定数 | 値 | 説明 |
SQLITE_ERROR | 1 | SQLエラー |
SQLITE_INTERNAL | 2 | 外部エラー |
SQLITE_PERM | 3 | 権限で取り扱えない |
SQLITE_ABORT | 4 | コールバックが中断を要求する |
SQLITE_BUSY | 5 | データベースファイルはロックされている |
SQLITE_LOCKED | 6 | テーブルがロックされている |
SQLITE_NOMEM | 7 | メモリ不足(malloc関数失敗) |
SQLITE_READONLY | 8 | 読込専用のデータベースに書き込むエラー |
SQLITE_INTERRUPT | 9 | 操作が中断された(sqlite3_interrupt()に) |
SQLITE_IOERR | 10 | ディスクI/O失敗 |
SQLITE_CORRUPT | 11 | The database disk image is malformed |
SQLITE_NOTFOUND | 12 | テーブルかレコードが存在しない(使用していない) |
SQLITE_FULL | 13 | データベースがFull |
SQLITE_CANTOPEN | 14 | データベースファイルを開けない |
SQLITE_PROTOCOL | 15 | データベースロックプロトコール(使用していない) |
SQLITE_EMPTY | 16 | データベースが空 |
SQLITE_SCHEMA | 17 | データベースのスキーマが変更された |
SQLITE_TOOBIG | 18 | 文字列かBLOBデータが大きすぎる |
SQLITE_CONSTRAINT | 19 | Abort due to constraint violation |
SQLITE_MISMATCH | 20 | データタイプが不適切 |
SQLITE_MISUSE | 21 | Library used incorrectly |
SQLITE_NOLFS | 22 | OS機能が支持されていない |
SQLITE_AUTH | 23 | アクセス権限がない |
SQLITE_FORMAT | 24 | Auxiliary database format error |
SQLITE_RANGE | 25 | パラメータの番号が範囲以外 |
SQLITE_NOTADB | 26 | 指定したファイルはデータベースフォーマットではない |
SQLITE_ROW | 100 | 後一行のデータが存在する |
SQLITE_DONE | 101 | 操作が正しく行われた |
拡張エラーコード一覧
定数 | 値 |
SQLITE_IOERR_READ | (SQLITE_IOERR | (1<<8)) |
SQLITE_IOERR_WRITE | (SQLITE_IOERR | (3<<8)) |
SQLITE_IOERR_SHORT_READ | (SQLITE_IOERR | (2<<8)) |
SQLITE_IOERR_FSYNC | (SQLITE_IOERR | (4<<8)) |
SQLITE_IOERR_DIR_FSYNC | (SQLITE_IOERR | (5<<8)) |
SQLITE_IOERR_TRUNCATE | (SQLITE_IOERR | (6<<8)) |
SQLITE_IOERR_FSTAT | (SQLITE_IOERR | (7<<8)) |
SQLITE_IOERR_UNLOCK | (SQLITE_IOERR | (8<<8)) |
SQLITE_IOERR_RDLOCK | (SQLITE_IOERR | (9<<8)) |
SQLITE_IOERR_DELETE | (SQLITE_IOERR | (10<<8)) |
SQLITE_IOERR_BLOCKED | (SQLITE_IOERR | (11<<8)) |
SQLITE_IOERR_NOMEM | (SQLITE_IOERR | (12<<8)) |
SQLITE_IOERR_ACCESS | (SQLITE_IOERR | (13<<8)) |
SQLITE_IOERR_CHECKRESERVEDLOCK | (SQLITE_IOERR | (14<<8)) |
SQLITE_IOERR_LOCK | (SQLITE_IOERR | (15<<8)) |
SQLITE_IOERR_CLOSE | (SQLITE_IOERR | (16<<8)) |
SQLITE_IOERR_DIR_CLOSE | (SQLITE_IOERR | (17<<8)) |
SQLITE_LOCKED_SHAREDCACHE | (SQLITE_LOCKED | (1<<8) ) |
[前のページへ]
2 thoughts to “SQLite使用説明(VC++言語)(3)”