C言語でSQLiteを利用する

スポンサーリンク

C言語でSQLiteを使ってみる その2

スポンサーリンク

テスト用のデータベースの内容

テーブル定義:

 

テーブルの内容:

 

 

 

C言語でSQLiteを用いたプログラム例について

ここでのプログラムは、あくまでプログラム例です。動作確認は自己責任でお願いします。また、エラー処理などはとても手を抜いています。動作したかどうかも終了ステータスだけで判断を行います。Windowsの終了ステータスの確認方法は、コマンドプロンプトで実行ファイルを実行した後に、

で確認することができます。終了ステータスが0の場合は正常終了、0以外の場合は異常終了とします。

 

 

 

データベースを開いて、閉じるだけのプログラム

簡単な説明

test.dbというデータベースを開いて、閉じるだけのプログラムです。

データベースハンドラは、ポインタ型で作成します。ハンドラとは、私たちが何かを操作するときに必要な参照もしくはオブジェクトのことです。今回はデータベースを操作するため、データベースハンドラといいます。

sqlite3_open()に渡すときは、データベースハンドラをさらにポインタにして、sqlite3_open()の生成するデータベースハンドラを受け取れるようにします。

今回はすぐにデータベースを閉じるため、次にsqlite3_close()で生成されたデータベースハンドラを解放します。

このプログラムを実行するときに、もしtestdb.dbが存在しない場合は、test.dbが作成されます。

 

 

 

SELECT文の実行

 

簡単な解説

sqlite3_prepare_v2()でプリペアドステートメント(prepared statement)を生成します。その後、sqlite_step()でSQL文の結果から1行読み取ります。sqlite3_prepare_v2()の第1引数は、データベースハンドラです。第2引数にSQL文を取り、第3引数にそのSQL文のバイト数ですが、負の値ならばヌル文字まで読み取ります。第4引数はプレペアドステートメントをポインタで渡します。第5引数は、第2引数と第3引数から読み取らなかったSQL文になります。

読み取った後に、sqlite3_column_int()やsqlite3_column_text()で、その行の値を読み取ります。sqlite3_column_int()やsqlite3_column_text()の2つ目の引数はSQL文結果のカラム名の順番を表しています。

今回の場合、結果はid, nameの順番で並びます。添え字は0から始まるため、0:id, 1:nameとなります。その結果をsqlite3_column_int()やsqlite3_column_text()の2つ目の引数で指定することで結果を取り出します。

行を読み取り終わったら、sqlite3_finalize()で生成されたプリペアドステートメントを解放します。

また、何かエラーが起きた時にsqliteの関数で返却されるコードをsqlite3_errmsg()に渡すことでエラーの内容を表示することができます。

 

 

 

INSERT文の実行

簡単な解説

sqlite3_prepare_v2()でINSERT文の準備をしています。INSERT文の実行例として値も直接書き込んでいます。sqlite3_step()で準備したINSERT文を実行します。その際、正常に動作したとき、sqlite3_step()での返却値のコードは、定数SQLITE_DONEになります。

sqlite3_prepare_v2()で使われている文字列の連結の仕方は、C言語に触っていないと少し忘れやすいテクニックだと思います。

 

 

 

INSERT文の実行(プレースホルダとバインド)

簡単な解説

プレースホルダを用いたINSERT文の例です。「プレースホルダ」とは、文字列の一部を別の文字列に置き換えるもののことです。この例では、「?」がプレースホルダです。もしくは、プレースホルダのことを「バインド変数」ともいいます。

また、プレースホルダに値を入れることを「バインド(bind)する」といいます。sqlite3_bind_int()やsqlite3_bind_text()で値をバインドします。第1引数は、sqlite3_prepare_v2()で生成したプレペアドステートメントです。第2引数はプレースホルダの位置で最初に現れたものが1となります。その後に現れるプレースホルダが、2,3…と続きます。第3引数が値になります。

sqlite3_bind_text()の第4引数はヌル文字のまでのバイト数で、ここが負の値の場合、ヌル文字まで自動で値をbindします。

sqlite3_bind_text()の第5引数はバインドした値のデストラクタになります。型はvoid(*)(void*)で、この引数にはバインドしたデータのポインタが入るため、これを利用してデータを解放する。また、バインドする値が決して変わらない場合は、定数SQLITE_STATICを使い、バインドする値が変化する場合は、定数SQLITE_TRANSIENTを使う。例えば、値をバインドするときに変数をバッファとして使いまわす場合などは、SQLITE_TRANSIENTを使う。

 

 

 

INSERT文の実行(プレースホルダとバインド)ループの形

簡単な解説

上のINSERT文の例をループの形にしてみただけの例です。

 

 

 

DELETE文の実行

簡単な解説

DELETE文でidが2のデータを削除してます。前回のINSERT文でのプレースホルダを活用すれば、プログラムはより良くなります。

 

 

 

UPDATE文の実行

簡単な解説

こちらもDELETE文と同じよう形で、idが1のデータで、nameを「xxx」に書き換えています。このプログラムも前回のINSERT文でのプレースホルダを活用すれば、より良いプログラムになります。

 

 

 

CREATE TABLE文の実行

実行結果

簡単な解説

CREATE TABLE文の実行例です。CREATE TABLE文でテーブルを作成した後に、テーブルが作成されたか確認をするために、sqliteのデータベースの作成時にできるsqlite_masterというテーブルを使って、データベース全体のテーブルを確認しています。

sqlite3_exec()は、「sqlite3_prepare_v2()→sqlite3_step()→sqlite3_finalize()」までの一連の流れを行ってくれるラッパー関数です。ラッパーとは、ラップ(wrap、包む)という単語からくる言葉で、sqlite3_exec()は「sqlite3_prepare_v2()→sqlite3_step()→sqlite3_finalize()」の流れをラップして(包んで)います。

sqlite3_exec()の第1引数はデータベースハンドラで、第2引数はSQL文です。第3引数は、ステートメントを読み取るごとに呼び出されるコールバック関数で、第4引数はそのコールバック関数に渡すことができる引数になります。第5引数で、エラーメッセージを受け取ることができます。

CREATE TABLE文などのような一回で終わるようなSQL文はsqlite3_exec()で実行すると非常に簡単で、また、SELECT文のようなSQL文でデータを読みだすときもコールバック関数を用いることで、非常に簡単にデータを読み出すことができます。

sqlite3_exec()のコールバック関数の引数は、第1引数はsqlite3_exec()の第4引数で、第2引数はSQL文の結果の行数で、第3引数はデータの値(の配列)で、第4引数がカラム名(の配列)となります。

 

 

 

TRANSACTIONの実行

簡単な解説

データベースでは、処理の一連の流れを処理する際にトランザクションを使います。トランザクションは、一連の流れのどこかが失敗してしまったら、トランザクションを始めた状態にデータベースの状態を戻すことができます。トランザクションを行えば、例えば銀行で、Aさんの口座から1000円ひかれて、Bさんの口座に1000円が入っていないというような状況を防ぐことができます。

SQLiteのトランザクションは「BEGIN TRANSACTION」でトランザクションを開始して、「COMMIT」で処理の完了、「ROLLBACK」でトランザクション前の状態に戻すことができます。

 

 

 

参考

SQLite Documentation(https://www.sqlite.org/docs.html)