본문 바로가기

Android/개념 및 예제

Android SQLite를 사용하여 데이터를 저장하기

 

SQLite는 오픈소스로 만들어진 관계형 데이터 베이스입니다. (https://www.sqlite.org/)

SQLite를 이용한 데이터는 파일에 저장되며 다음과 같은 경로에 저장됩니다.

data/data/[package_name]/databases

Android에서 데이터베이스를 사용할 때 필요한 API는 android.database.sqlite 패키지로 제공됩니다.

 

SQLiteOpenHelper 클래스를 사용하여 데이터베이스 생성하기

SQLiteOpenHelper 클래스에는 데이터베이스 관리를 위한 유용한 API 세트가 포함되어 있습니다.

이 클래스를 사용하여 데이터베이스의 참조를 가져오면 시스템은 앱이 시작되고 있는 동안이 아닌 필요한 때에만 데이터베이스 생성 및 업데이트와 같이 장시간 실행될 수 있는 작업을 실행합니다.

개발자는 getWritableDatabase() 또는 getReadableDatabase()를 호출하기만 하면 됩니다.

SQLiteOpenHelper는 추상 클래스이므로 서브 클래스를 만들어 사용해야 합니다.

 

class DBHelper(
    context: Context?,
    name: String?, // 데이터 베이스 이름
    factory: SQLiteDatabase.CursorFactory? = null, // null을 기본 값으로 함
    version: Int // 데이터 베이스 버전
) : SQLiteOpenHelper(context, name, factory, version){

    override fun onCreate(db: SQLiteDatabase?) {
        // 테이블 생성
        val memoSQL = "create table tb_memo (" +
                "_id integer primary key autoincrement," +
                "title," +
                "content)"
        db?.execSQL(memoSQL)
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        // 기존 테이블 제거후 다시 생성하기
        db?.execSQL("drop table tb_memo")
        onCreate(db)
    }
}

SQLiteOpenHelper를 사용하려면 onCreate(), onUpgrade()를 재정의해서 사용해야 합니다.

  • onCreate() : 앱이 설치되어 SQLiteOpenHelper가 최초로 사용되는 순간 호출됩니다.
  • onUpgrade() 데이터 베이스 버전이 변경될 때마다 호출됩니다.

 

SQLiteDatabase 클래스

SQLite의 핵심 클래스는 SQLiteDatabase입니다.

데이터 베이스에 데이터를 저장하고, 가져오고, 수정, 삭제하는 sql를 SQLiteDatabase의 함수를 이용하여 수행합니다.

  • execSQL(String sql, Object[] bindArgs) : select가 아닌 insert, update, delete 등 나머지 sql 실행
  • rawQuery(String sql, String[] selectionArgs) : select sql 실행

 

execSQL() 함수로 insert문을 실행하기

다음은 SQLiteOpenHelper와 execSQL() 함수로 insert문을 실행한 예시입니다.

val helper = DBHelper(this,"memodb", null, DATABASE_VERSION)
val db:SQLiteDatabase = helper.writableDatabase
// insert Sql 실행
db.execSQL(
    "insert into tb_memo (title, content) values (?,?)",
    arrayOf(title, content)
)
db.close()
  • SQLiteOpenHelper를 사용해 데이터 베이스를 생성하고
  • SQLiteOpenHelper의 getWritableDatabase() 함수를 통해 SQLiteDatabase를 객체를 생성합니다.
  • execSQL()을 통해 insert문을 실행하고 데이터를 저장합니다.
insert문에서 "~ values (?,?)"라고 작성하면 각각의 ?에 대응하는 데이터를 배열을 통해 넣어줘야 합니다.

 

rawQuery() 함수로 select문을 실행하기

val helper = DBHelper(this,"memodb", null, MainActivity.DATABASE_VERSION)
val db = helper.writableDatabase
// select Sql 실행
val cursor = db.rawQuery("select title, content from tb_memo order by _id desc limit 1", null)

// 다음행 가져오기
while (cursor.moveToNext()) {
    // 다음 열 가져오기
    titleView.text = cursor.getString(0)
    contentView.text = cursor.getString(1)
}
db.close()

sql에 ? 표현이 없어 두 번째 매개변수 값이 null입니다. rawQuery의 응답 값은 Cursor 객체입니다.

Cursor 객체는 선택된 행의 집합 객체입니다.

여기서 각 열에 해당하는 데이터를 획득하려면 Cursor 객체를 이용해 행을 선택하고 선택된 행의 열 데이터를 획득하는 구조입니다.

위의 예시는 moveToNext() 함수를 통해 다음 행을 가져오고 getString() 함수를 통해 열 데이터를 가져옵니다.

매개변수의 0,1은 몇 번째 열 데이터를 가져오는지를 지정합니다.

Cursor의 다음 메서드를 통해 원하는 행을 가져올 수 있습니다.

  • moveToNext(): 순서상으로 다음 행 선택
  • moveToFirst(): 가장 첫 번째 행 선택
  • moveToLast(): 가장 마지막 행 선택
  • moveToPrevious(): 순서상으로 이전 행 선택

insert( ), query( ), update( ), delete( ) 함수 이용

execSQL(), rawQuery() 함수 이외에 다음의 함수를 이용해도 SQL 문을 수행할 수 있습니다.

execSQL(), rawQuery() 함수는 개발자가 직접 SQL 문을 매개변수로 전달해야 했지만

위 4가지 함수는 sql문을 만들기 위한 정보만 매개변수로 전달하면 자동으로 SQL 문을 만들어 실행해줍니다.

이 중 insert()와 update()는 ContentValues 클래스를 매개변수로 넘깁니다. key는 실제 테이블의 열 이름입니다.

ContentValues는 insert, update의 데이터를 key-value 형식으로 표현합니다.

  • insert(String table, String nullColumnHack, ContentValues values)
  • update(String table, ContentValues values, String whereClause, String[] whereArgs)
  • delete(String table, String whereClause, String[] whereArgs)
  • query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,
  • String having, String orderBy, String limit)

 

3번의 execSQL() 함수를 insert( ) 함수로 변경하면 다음과 같이 나옵니다.

val helper = DBHelper(this,"memodb", null, DATABASE_VERSION)
val db:SQLiteDatabase = helper.writableDatabase
// insert Sql 실행
var contentValues = ContentValues()
contentValues.put("title",title)
contentValues.put("content",content)

db.insert("tb_memo", null, contentValues)
db.close()