Help us understand the problem. What is going on with this article?

よく使うのでAndroidでDB関連のことをメモ。

はじめに

これはメモなので悪しからず。

1.継承と定数とDBファイルの生成

カラム(横軸)はID(自動生成)categorychapterpasswordの四つ。ファイルの名前はProjectList.dbでテーブル名はPROJECT_INFO

SampleDatabaseHelper
public class SampleDatabaseHelper extends SQLiteOpenHelper {
    // Reference
    private static final String TAG = "SampleDatabaseHelper";
    // テーブルの名前
    private static final String TABLE_PROJECT = "PROJECT_INFO";
    // カラム
    public static final String ID = "_id";
    public static final String CATEGORY = "category";
    public static final String CHAPTER = "chapter";
    public static final String PASSWORD = "password";

    // 全部のカラム
    private final String[] PROJECT_COLUMNS = {
            CATEGORY,
            CHAPTER,
            PASSWORD,
    };

    // SQliteの制作文
    private static final String SQL_CREATE_TABLE_PROJECT = "CREATE TABLE `"
            + TABLE_PROJECT + "` ("
            + "`" + ID + "` INTEGER PRIMARY KEY AUTOINCREMENT,"
            + "`" + CATEGORY + "`    TEXT NOT NULL,"
            + "`" + CHAPTER + "`    TEXT NOT NULL,"
            + "`" + PASSWORD + "`,"
            + "UNIQUE(`" + CATEGORY
            + "`, `" + CHAPTER
            + "`, `" + PASSWORD
            + "`));";

    // ファイル名とバージョン番号の定義
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_FILE_NAME = "ProjectList.db";

    // コンストラクタ
    public SampleDatabaseHelper (Context context) {
        super(context, DATABASE_FILE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate (SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(SQL_CREATE_TABLE_PROJECT);
    }

    @Override
    public void onUpgrade (SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

【参考】SQLiteのテーブル作成コマンド

CREATE TABLE `PROJECT_INFO`(
`_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`category` TEXT NOT NULL,
`chapter` TEXT NOT NULL,
`password`,
UNIQUE(`category`, `chapter`, `password`));

CREATE TABLEの後ろにテーブル名。()内にカラム 型 規則の順で,で区切る。規則には、主キーを指定するPRIMARY KEY、行が追加された時、値を1ずつ増やして自動生成するAUTOINCREMENT、絶対空ではいけないNOT NULL等がある。また、UNIQUEで囲まれたカラムの値は他行と同じ組み合わせにはなれなくなる。

2.登録メソッド

SampleDatabaseHelper
/**
 * 与えられた値を登録して登録できたかを返す。
 * 
 * @param category カテゴリーの値。
 * @param chapter チャプターの値
 * @param password パスワードの値
 * 
 * @return 登録に成功したらtrueを、失敗したらfalseを返す。。
 */
public boolean addProject(final String category, final String chapter, final String password) {
        try{
            SQLiteDatabase db = getReadableDatabase();
            final ContentValues values = new ContentValues(3);
            values.put(CATEGORY,category);
            values.put(CHAPTER,chapter);
            values.put(PASSWORD,password);
            long rowID = db.insert(TABLE_PROJECT,null,values);
            if (rowID >= 0) {
                // 登録に成功。
                return true;
            } else {
                // 登録に失敗。UNIQUEの条件に引っかかったことが原因の場合が多い。
                return false;
            }
        } catch (Throwable allErrors) {
            // なんかしらのエラー
            return false;
        }
    }

3.行の削除

SampleDatabaseHelper
/**
 * 特定の行を削除(IDは永久欠番)
 * 
 * @param id 削除対象の行のID
 * @return 削除した行のID(?)
 */
public int deleteProject(String id){
    String selection = ID + " = ?";
    String[] selectionArgs = {
            id
    };
    SQLiteDatabase db = getWritableDatabase();
    return db.delete(TABLE_PROJECT, selection, selectionArgs);
    }

selectionは条件文であり、sqliteの書き方である。この場合、?は一つだが、複数あるときでもselectionArgsの内容がが一つずつ?にあてはめられる。

4.IDからカラムを検索

SampleDatabaseHelper
/**
 * IDからカラムを取得
 * 
 * @param id 検索対象の行のID
 * @return ヒットした行の内容がcategory chapter passwordの順で並んだ配列
 */
public String[] getProjectColumns(String id){
        // 条件文
        String selection = ID + " = ?";
        // 実際の値
        String[] selectionArgs = {
                id
        };
        //カーソル。データベースの行をさす、ポインタみたいなもの。該当する行をマークしておいてくれる。
        Cursor c = null;
        // dbファイルの取得
        SQLiteDatabase db = getReadableDatabase();
        try {
            // 検索
            c = db.query(
                    /*テーブル名*/ TABLE_PROJECT,
                    /*求めるもの*/ PROJECT_COLUMNS,
                    /* 条件文 */ selection,
                    /* 実際の値 */ selectionArgs,
                    /*グループ化*/ null,
                    /*having(?)*/ null,
                    /*ソート  */ null
            );
            if (c.moveToNext()/*抽出した行から一つ目の行をとる*/) {
                // ちゃんと値がある。
                // 目的のものが中に入ってる。PROJECT_COLUMNSの順番。
                String[] ret = {
                        c.getString(0),
                        c.getString(1),
                        c.getString(2)
                };
                return ret;
            }
        }catch (Exception e) {

        } finally {
            if (c != null) {
                try {
                    // カーソルを閉める。
                    c.close();
                } catch (Exception ex) {}
            }
        }
        return null;
    }

カーソルの概念に注意。いっぱい列がある中で検索にヒットしたものはマークされて抽出せれる。その状態ではすべてがマークされているが、c.moveToNext()をすることで抽出されたもののなかで一番上の一つのみにカーソルが移る。(さらにもう一回やると抽出されたもののなかで次にいく)これを利用して、値が中に入ってることを確かめることができる。

まぁ今回はIDで調べているので一つしかマークされないんですけどね。

5.カラムからIDを検索

特に利便性はないかも

SampleDatabaseHelper
/**
 * カラムからIDを取得。
 *
 * @param category 検索用のカテゴリー
 * @param Chapter 検索用のチャプター
 * @param Password 検索用のパスワード
 * @return ヒットしたID
 */
public String getProjectID (String category, String chapter, String password) {
        String[] columnsOfID = {
                ID
        };

        // selectionと同じ順番で値が適応される。
        String[] selectionArgs = {
                category,
                chapter,
                password
        };

        // 複数条件ではANDをつかう。
        String selection = CATEGORY + " = ? AND " + CHAPTER + " = ? AND " + PASSWORD + " = ?";
        SQLiteDatabase db = getReadableDatabase();
        Cursor c = null;
        try {
            c = db.query(
                    TABLE_PROJECT,
                    columnsOfID,
                    selection,
                    selectionArgs,
                    null,
                    null,
                    null
            );
            if (c.moveToNext()) {
                // 一つだけなので配列では返さない。
                return c.getString(0);
            }
        } catch (Exception e) {

        } finally {
            if (c != null) {
                try {
                    c.close();
                } catch (Exception ex) {}
            }
        }
        return null;
    }

selectionの複数条件と、selectionArgsとの順番をそろえることろが大事。

まとめ

メモ程度なのでスペルとかは言ってくれると直します。
メソッドの仕様を企業規格的に書いてみました。日本語ですが。
Twitter: https://twitter.com/Cyber_Hacnosuke (フォローしてくださいお願いします。)
Github: https://github.com/CyberHacnoshuke

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away