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

# はじめに
これはメモなので悪しからず。
# 1.継承と定数とDBファイルの生成
カラム(横軸)は```ID(自動生成)```、```category```、```chapter```、```password```の四つ。ファイルの名前は```ProjectList.db```でテーブル名は```PROJECT_INFO```

```java: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のテーブル作成コマンド

```sql
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.登録メソッド

```java:SampleDatabaseHelper
    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 (Exception e) {
            return false;
        }
    }
``` 

# 3.行の削除

```java:SampleDatabaseHelper
    public int deleteProject(String id){
        String selection = ID + " = ?";
        String[] selectionArgs = { id };
        try {
            SQLiteDatabase db = getWritableDatabase();
            int deletedId = db.delete(TABLE_PROJECT, selection, selectionArgs);
            return deletedId;
        } catch (Exception e) {}
    }
```
``selection``は条件文であり、sqliteの書き方である。この場合、``?``は一つだが、複数あるときでも``selectionArgs``の内容がが一つずつ``?``にあてはめられる。

# 4.行の検索
```java:SampleDatabaseHelper
    public List<String[]> getProjectColumns(String category){
        String selection = CATEGORY + " = ?";
        String[] selectionArgs = { category };
        Cursor c = null;
        try {
            SQLiteDatabase db = getReadableDatabase();
            c = db.query(TABLE_PROJECT, PROJECT_COLUMNS, selection, selectionArgs, null, null, null);
            List<String[]> list = new ArrayList<>();
            while (c.moveToNext()) {
                String[] ret = { c.getString(0), c.getString(1), c.getString(2) };
                list.add(ret);
            }
            return list;
        }catch (Exception e) {

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

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

```java:SampleDatabaseHelper
    public String[] getProjectColumns(String id) {
        String selection = ID + " = ?";
        String[] selectionArgs = { id };
        Cursor c = null;
        try {
            SQLiteDatabase db = getReadableDatabase();
            c = db.query(TABLE_PROJECT,PROJECT_COLUMNS, selection, selectionArgs, null, null, null);
            if (c.moveToNext()) {
                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;
    }
```

# 5.行の更新

```java
    public boolean updateColumns(String id, String newCategory, String newChapter, String newPassword){
        String selection = ID + " = ?";
        String[] selectionArgs = { id };
        try {
            SQLiteDatabase db = getReadableDatabase();
            final ContentValues updateValues = new ContentValues(3);
            updateValues.put(CATEGORY,newCategory);
            updateValues.put(CHAPTER,newChapter);
            updateValues.put(PASSWORD,newPassword);
            db.update(DATABASE_PROJECT_NAME, updateValues, selection, selectionArgs);
            return true;
        }catch (Exception e) {
            return false;
        }
        return false;
    }
```



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