世界を目指せ!Androidアプリ開発入門を見てSQLiteについて、調べました。
SQLiteで扱えるデータ型は以下の5種類で非常にシンプルです。
INTEGER 符号付整数
REAL 浮動小数点
TEXT テキスト
BLOB バイナリデータ
NULL NULL
データベースの中に入れる要素は上記のシンプルなものでした。
■SQLiteOpenHelperというヘルパークラスを継承してDBOpenHelperクラスを作成
public DBOpenHelper( Context context ){ super( context, <<データベース名>>, null, <<データベースのバージョン番号>>); }
ですが、第3引数はCursorFactoryをいれます。CursorFactoryに関しては
で調べたところ。基本的に気にしなくてOKのようです。
"データベースのクエリ結果に対してカーソルが特別な操作や検証などをやるような 自作のカーソルクラスを拡張したものを作るときには、このカーソルを渡す"
カーソルをまだ把握しきれてないのですが自作してない限りはnullにしときます。
また、データベースのバージョン番号に関してですが、
で調べたところ、バージョン自体は任意で決めてよいみたいです。
その代わりデータベースのバージョンを変えるとその時に実行してくれる関数があるので、更新作業などをしてデータベース構成を変えた場合に、onUpgradeで変換を行う処理を書いておけば、よいようです。
■SQLiteDatabaseの最初にテーブルを作成する。
@Override public void onCreate(SQLiteDatabase db) { db.execSQL( "CREATE TABLE IF NOT EXISTS Test ( _id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , caption TEXT )" ); }
Testと言うクラスが存在していなかった場合には、テーブルを作成します。()の中の意味が若干不明ですが。。とおもってたら分かりました!
テーブルの中に_idと言うINTEGER(整数)を作成して、勝手の増えていく(1,2,3,4…)で空じゃないよ。あと、captionと言うTEXT(文字列)も一緒に作成ね。
と言う意味のようです「,」を使う事で好きなだけテーブルの要素を作成できるようです。
■onUpgrade使用例
アップグレードも下記で使っていました。上記で調べたとおりな感じです。
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if( oldVersion == 1 ) { // アップグレードコード db.execSQL( "ALTER TABLE Test add add_text TEXT" ); } }
現在のデータのバージョン番号と比較を行えるようです。
■レコードの追加
public void add( String caption ) { ContentValues val = new ContentValues(); val.put( "caption", caption ); m_db.insert( TBL_NAME, null, val ); }
でレコードってなんだろうか。。と考えると、
val.put( "キー",値);
を入れてくれるのかと思いました。つまりは
val.put( "身長",177); val.put( "体重",65);
のような感じ。もちろん最初のテーブルを作る段階で指定をしたキーしか使えないとは思うのだけど。。
■レコードの更新
public void update( int id, String caption ) { ContentValues val = new ContentValues(); val.put( "caption", caption ); m_db.update( TBL_NAME, val, "_id=?", new String[] { Integer.toString( id ) }); }
updateではidがこの値であるものを検索してそれをupdateする。?の中にその次の引数の{id}が入るイメージです。
■レコードの削除
public void delete( int id ) { m_db.delete( TBL_NAME, "_id=?", new String[] { Integer.toString( id ) }); }
仕組みは上記の更新と同じようです。
■レコードの読み出し
public String[] loadAll(){ int i; Cursor c; String[] entries; if( m_db == null )return null; c = m_db.query( TBL_NAME,new String[] { "_id", "caption" },null, null, null, null, null ); int numRows = c.getCount(); c.moveToFirst(); entries = new String[numRows]; for( i = 0; i < numRows; i++ ){ entries[i] = c.getString(1); c.moveToNext(); } c.close(); return entries; }
最初にデータベースが存在するかの確認
idとcaptionの値を取り出すと宣言。
getCountでいくつ存在するかの確認。
moveToFirst()で一番上から検索を行う確認。
cからgetString(1)で、値を取得して、(多分要素のcaptionを指定している。)
c.moveToNext();で次々に進めていく。
ですが、getStringって意味そのまま取ると「文字列を取得」なので、おかしい。。と思ったら、やはり型に合わせて取得をする方法を変更してgetIntなどもあるようです。
■queryの使い方
m_db.query( TBL_NAME,new String[] { "_id", "caption" },null, null, null, null, null );
でnullばっかりで気持ちが悪かったので、引数を調べてみました。
●第一はテーブル名
●第二が取得のレコード指定
●第三がWHERE句
●第四がWHERE句指定の値
WHRER句とは
検索の条件を与える事ができる。 更新に関してもWHERE句を利用していたのを実感ですが、例えば 第三引数が "id >= ?" で第四引数が {"3"} であれば検索の条件を _idが3以上と言う事になります。
●第五がGROUP BY句
GROUP BY句については下記を参照しました
GROUP BY句とは 同じ値を持つデータごとに集合化することをいいます。 その集合の中で最大の値を取得できるようです。 イメージとしては、 1組の中で最高得点は95点 2組の中で最高得点は87点 3組の中で最高得点は82点 4組の中で最高得点は93点 5組の中で最高得点は89点 のような事が可能な値のようです。
●第六がHAVING句
HAVING句についても下記を参照しました
HAVING句に関しては、 WHERE句のグループ版で。例えば上のイメージを元に 90点以上の子がいたクラスは 1組の中で最高得点は95点 4組の中で最高得点は93点 のような感じです。
●第七はORDER BY句
ORDER BY句については これは並び順を決定する為の要素を指定します。 身長順、名前順、などなどです。
全体の長さを取得しなくても次の要素があるか無いかの判別をmoveToNextでもできるので、また、各要素毎のIndexがgetColumnIndex(“キー”)でできるので
while(c.moveToNext()){ entries[i] = c.getString(c.getColumnIndex("caption")); }
の方がスマートかと思います。
これに続いて
でも勉強をしました。割とおおざっぱな説明だったのですが、
軽量化の方法に関しては
for (String s : array) { db.execSQL(“insert into table values (‘” + s + “’);”); }
を下記のようにすると、実行速度が倍近くになるようです。
db.beginTransaction(); try { SQLiteStatement stmt = db.compileStatement("insert into table values (?);"); for (String s : array) { stmt.bindString(1, s); stmt.executeInsert(); } db.setTransactionSuccessful(); } finally { db.endTransaction(); }
中身を見ていると、stmtの中にステートメントを貯めて、一気に実行を行っているようです。
以上でSQLiteに関して大体をつかめて来た気がします。