본문 바로가기
컴퓨터/안드로이드

[안드로이드] 데이터베이스 생성 및 조회/SQLite 사용하기

by 도도새 도 2022. 7. 3.

SQLite 사용

 

안드로이드는 SQLite라는 데이터베이스를 지원한다. SQLiteSQL 명령어를 이용하여 만들 수 있는 비교적 가벼운 데이터베이스라고 할 수 있다.

 

이 데이터베이스에 저장되는 데이터는 직업, 연락처, 나이 같이 반복적이고 구조화된 데이터가 이상적이다.

 

그렇다면 왜 데이터베이스를 쓸까? 바로 앱을 껐다가 켜더라도 내가 만든 데이터구조가 그대로 사용자의 휴대전화에 저장되어 있을 수 있기 때문이다. 즉 이번에 한 작업을 다음에 불러와 사용 가능하다는 것이다.

 

게다가 sql문을 그대로 쓰고, db파일을 만들기 때문에 이식성이 상승한다.

 

오늘은 이 안드로이드 SQLite를 이용하여 데이터를 사용자로부터 입력받아 저장하고 확인하는 예제를 작성한다.

 

1. SQLiteOpenHelper

 

 안드로이드에서 SQLite 데이터베이스를 만드는 방법은 크게 두 가지가 있는데, 바로 SQLiteOpenHelp를 사용하느냐 그렇지 않느냐이다. 

 

SQLiteOpenHelper 클래스에는 데이터베이스 관리를 위한 API세트가 포함되어있다. SQLiteHelper를 이용하여 DB를 생성하면 데이터베이스의 유지 보수, 예를들어 업데이트 등이 편리하다.

 

이후, 해당 클래스를 이용해 getWritableDatabase() 메서드를 호출하기만 하면 SQL파일이 만들어지게된다. 어떤 방식으로 데이터베이스를 만들던지 만들던지 SQL파일은 사용자의 내부 저장소에 비공개 폴더로 저장된다.

 

(DatabaseHelper.kt)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class DatabaseHelper(context: Context, name:String = "affsfsda2.db", version:Int = 1)
    :SQLiteOpenHelper(context, name, null, version){
 
    override fun onCreate(db: SQLiteDatabase?) {
        Log.d("onCreate""onCreate called")
    }
 
    override fun onOpen(db:SQLiteDatabase?){
        Log.d("onOpen""onOpen called")
    }
 
    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        Log.d("onUpgrade""onUpgrade called ${oldVersion} -> ${newVersion}")
    }
}
 
cs
 

DatabaseHelper라는 코틀린 클래스 파일을 생성한다.

1. SQLiteOpenHelper상속을 입력한 후 Ctrl + I를 입력하면 onCreate메서드와 onUpgrade메서드를 쉽게 구현할 수 있다.

두 메서드를 모두 클릭한 후, OK버튼을 누르면 된다. 각각 데이터베이스가 만들어졌을 때, 그리고 열렸을 때 호출되는 메서드이다.

 

 

MainActivity.kt

 

MainActivity에 코드를 작성한다.

 

(MainActivity.kt)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class MainActivity : AppCompatActivity() {
    var cnt = 0;
    lateinit var dbHelper:DatabaseHelper
    lateinit var database:SQLiteDatabase
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        var tableName:EditText = findViewById(R.id.edittext0)
        var textview:TextView = findViewById(R.id.textview)
        var btn_createDb:Button = findViewById(R.id.btn_createDatabase)
        var btn_createTable:Button = findViewById(R.id.btn_createTable)
        var btn_verify:Button = findViewById(R.id.btn_verifyTable)
        var btn_insertRecord:Button = findViewById(R.id.btn_insertRecord)
        btn_createDb.setOnClickListener {
                dbHelper = DatabaseHelper(this)
                database = dbHelper.writableDatabase
                Log.d("생성 from 메인""데이터베이스 생성")
        }
 
        btn_createTable.setOnClickListener{
            var tableN = tableName.getText().toString()
            if(tableN == ""){
                Toast.makeText(this"테이블명을 입력하세요", Toast.LENGTH_SHORT).show()
            }
            else{
                var sql:String = "create table if not exists ${tableN}(" +
                        " _id integer PRIMARY KEY autoincrement, " +
                        " name text, " +
                        " age integer, " +
                        " mobile text)"
                database.execSQL(sql)
                Log.d("테이블 생성""이름:${tableN}")
            }
        }
 
        btn_insertRecord.setOnClickListener {
            var tableN = tableName.getText().toString()
            var sql:String = "insert into ${tableN} " +
                    "(name, age, mobile) "+
                    " values " +
                    "( 'Johon', '${cnt++}', '010-1110-1111')"
            database.execSQL(sql)
            Log.d("레코드 추가""${cnt}")
        }
 
        btn_verify.setOnClickListener {
            var tableN = tableName.getText().toString()
            var cursor:Cursor = database.rawQuery("select _id, name, age, mobile from ${tableN}"null)
            var recordCount = cursor.getCount()
            println("레코드 개수 : " + recordCount)
 
            for(i:Int in 1..recordCount){
                cursor.moveToNext()
                var id = cursor.getInt(0)
                var name = cursor.getString(1)
                var age = cursor.getInt(2)
                var mobile = cursor.getString(3)
 
                println("레코드 # ${id}, ${name}, ${age}, ${mobile}")
            }
        }
    }
}
cs

 

9 ~ 14 : 레이아웃의 각 요소를 객체화한다.

15 : 버튼을 클릭하면 데이터베이스를 생성한다.

21 : 버튼을 클릭하여, 입력받은 이름의 테이블을 생성및 실행한다.

37 : 버튼을 클릭하여 입력받은 이름의 테이블에 레코드를 추가, 실행한다.

47 : 버튼을 클릭하여 입력받은 테이블 이름의 요소를 모두 출력한다. 데이터 출력은 Cursor객체를 이용하게된다.

53~ : 데이터베이스의 행을 다음으로 옮겨가며, 각 컬럼의 값을 저장 및 출력한다.

 

activity_main.xml

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn_createDatabase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="데이터베이스 생성"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/edittext0"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_createTable"
            android:layout_weight="2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="테이블 생성"/>
    </LinearLayout>
    <Button
        android:id="@+id/btn_insertRecord"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="레코드 추가"/>
    <Button
        android:id="@+id/btn_verifyTable"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="테이블 조회>"/>
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:id="@+id/textview"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        </LinearLayout>
    </ScrollView>
</LinearLayout>
cs

 

출력 결과

 

SQL예제

 

실행 순서

1. table0 입력 -> 테이블 생성 버튼 클릭

2. 레코드 추가 3회 클릭

3. table1 입력 ->테이블 생성 버튼 클릭

3. 레코드 추가 3회 클릭

4. table0 입력 -> 테이블 조회 클릭

5. table1 입력 -> 테이블 조회 클릭

각 테이블에 레코드가 추가되고, 테이블 명에 따라 레코드 출력 결과가 달라짐(저장된 데이터에 따라 달라짐)을 확인 할 수 있다.

 

직관적으로 DB확인하기

 

앞서 안드로이드 기기 내에 데이터베이스가 저장된다고 말한 바 있다. 그렇다면 저장된 데이터베이스를 내가 가져와서 기기 외부에서 보는 것이 가능할까? 가능하다.

 

안드로이드 앱의 SQL데이터베이스 확인

 

1. 데이터 베이스 저장

안드로이드 스튜디오 상단의 [View] -> [Tool Windows] -> [Device File Explorer] 클릭

 

Device File Explorer에서 /data/data/[package name]/databases/ 디렉토리 확인

데이터베이스이름.db 우클릭 -> save as

 

2. 데이터 베이스 확인

 

이렇게 저장한 db파일을 열려면 Database Browser라는 툴을 설치해야한다. 아래의 사이트에서 자신의 운영체제에 맞는 툴을 설치하자.

https://sqlitebrowser.org/dl/

 

Downloads - DB Browser for SQLite

(Please consider sponsoring us on Patreon 😄) Windows Our latest release (3.12.2) for Windows: Windows PortableApp Note - If for any reason the standard Windows release does not work (e.g. gives an error), try a nightly build (below). Nightly builds ofte

sqlitebrowser.org

 

이후 툴에서 방금 저장한 db파일을 열면 쉽게 데이터베이스 구조를 알 수 있게 된다.

 

2-1 데이터 구조 보기

 

데이터 베이스를 툴에 올리면 바로 데이터 구조가 보인다.

 

SQLite db 확인

방금 만든 table0와 table1이라는 테이블이 보인다. (aa와 aaa는 사전에 본인이 만든 다른 테이블)

 

2-2 데이터 보기

 

각 테이블의 데이터 역시 확인이 가능하다.

table0

방금 앱에서 삽입했던 데이터들이 제대로 들어가 있음을 볼 수 있다.

댓글