안드로이드

[안드로이드] Database(데이터베이스) SQLite / SQLiteOpenHelper

edit0 2021. 1. 16. 01:19

데이터베이스는 데이터가 저장되어 있는 공간이라고 생각할 수 있다. 이 데이터베이스는 우리가 어떤 시스템을 만들거나 앱을 만들 때 데이터를 저장해놓기 위해서 필수적으로 필요한 수단인 만큼 활용성이 크고 많이 사용된다. 데이터베이스에도 여러 종류가 있는데 현재 가장 많이 사용되는 것은 관계형 데이터베이스로 오라클, MySQL, 마리아디비, 몽고디비 등 여러 종류가 있다. 오늘은 안드로이드 내에 작은 임베디드 데이터베이스로 개발된 경량급 관계형 데이터베이스인 SQLite를 활용하는 방법을 알아보도록 하겠다.

 

SQLite는 서버에서 사용되는 큰 데이터베이스들과 같이 표준SQL을 지원한다. 이것은 기존에 웹이나 PC에서 사용하던 업무용 앱의 데이터 관리 기능을 그대로 사용할 수 있다는 것이다.

 

데이터베이스를 사용하는 방법은 먼저 데이터베이스를 만들고, 그 안에 테이블을 만들고, 테이블 안에 레코드(데이터)를 추가해주고, 조회를 할 수 있다. 

위에 문장 그대로 순서대로 하나하나씩 하면 만들 수 있다. 좀 더 나아가면 테이블 간의 관계, 조인 등 더 활용되는 것이 있는데 그건 데이터베이스에 대해 따로 공부를 해야할 필요가 있다.

 

기본적으로 데이터를 다루는데 있어서 SELECT: 조회, INSERT: 입력, DELETE: 삭제, UPDATE: 수정(업데이트) 정도만 알고 있으면 된다.

 

주요 메소드

  • openOrCreateDatabase(데이터베이스 이름, 사용모드, CursorFactory): 데이터베이스 생성
  •  rawQuery(): 데이터 조회를 할 때 Cursor 객체를 반환 받기 위해 사용
  • Cursor 객체: 테이블에 들어있는 각각의 레코드를 순서대로 접근할 수 있도록 제공
  • moveToNext(): 레코드를 순차적으로 넘겨줌

이 정도면 이해했다면 아래 코드는 바로 이해될 것 이다.

 

코드

 

activity_main.xml

<?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">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="데이터베이스 생성"
            android:id="@+id/button1"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edittext1"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="테이블 생성"
            android:id="@+id/button2"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edittext2"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="레코드(데이터) 추가"
            android:id="@+id/button3"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext3_1"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext3_2"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext3_3"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="데이터 조회"
            android:id="@+id/button4"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edittext4"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="레코드 수정"
            android:id="@+id/button5"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext5_1"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext5_2"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext5_3"/>

    </LinearLayout>


    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/textview1"
        android:textSize="20dp"/>

</LinearLayout>

 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    Button b1,b2,b3,b4,b5;
    EditText et1,et2,et3_1,et3_2,et3_3,et4,et5_1,et5_2,et5_3;
    TextView tv1;

    SQLiteDatabase sqLiteDatabase;
    String table_name;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        b1 = findViewById(R.id.button1);
        b2 = findViewById(R.id.button2);
        b3 = findViewById(R.id.button3);
        b4 = findViewById(R.id.button4);
        b5 = findViewById(R.id.button5);

        et1 = findViewById(R.id.edittext1);
        et2 = findViewById(R.id.edittext2);
        et3_1 = findViewById(R.id.edittext3_1);
        et3_2 = findViewById(R.id.edittext3_2);
        et3_3 = findViewById(R.id.edittext3_3);
        et4 = findViewById(R.id.edittext4);
        et5_1 = findViewById(R.id.edittext5_1);
        et5_2 = findViewById(R.id.edittext5_2);
        et5_3 = findViewById(R.id.edittext5_3);

        tv1 = findViewById(R.id.textview1);

        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    createDatabase(et1.getText().toString()); //데이터베이스 생성/열기
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        });

        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    table_name = et2.getText().toString();
                    createTable(et2.getText().toString()); //테이블 생성
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        b3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                //데이터 입력
                    insertData(table_name, et3_1.getText().toString(), Integer.parseInt(et3_2.getText().toString()),et3_3.getText().toString());
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        b4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                //데이터 조회
                    selectData(table_name, et4.getText().toString());
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        b5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                //데이터 업데이트
                    updateData(table_name, et5_1.getText().toString(), Integer.parseInt(et5_2.getText().toString()),et5_3.getText().toString());
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });


    }

    private void createDatabase(String database_name){
        if(sqLiteDatabase == null) {
            printLn("데이터베이스 생성 / " + database_name);
            sqLiteDatabase = openOrCreateDatabase(database_name, MODE_PRIVATE, null);
        }
        else{
            printLn("데이터베이스 이미 생성됨");
        }

    }

    private void createTable(String table_name){
        if(sqLiteDatabase != null) {
            printLn("테이블 생성 / " + table_name);
            sqLiteDatabase.execSQL("create table " + table_name + "(id integer primary key autoincrement, name text, age integer, major text);");
        }
    }

    private void insertData(String table_name, String name, int age, String major){
        if(sqLiteDatabase != null){
            printLn("데이터 입력 완료");
            String query = "insert into "+table_name + "(name, age, major) VALUES(?, ?, ?);";
            Object[] params = new Object[]{name, age, major};

            sqLiteDatabase.execSQL(query, params);
        }
    }

    private void selectData(String table_name, String id){
        if(sqLiteDatabase != null){
            printLn("데이터 조회");
            String query = "select * from " + table_name + ";"; //조회할 쿼리문

            //rawQuery()메소드로 데이터 정보를 가져오고 Cursor 객체를 반환
            Cursor cursor = sqLiteDatabase.rawQuery(query,null);

            for (int i=0;i<cursor.getCount();i++) { //Cursor 객체에 있는 데이터 수만큼 반복
                cursor.moveToNext(); //다음 커서로 넘기기
                //cursor의 컬럼인덱스는 0부터 시작함, 현재 0은 id로 출력하지 않음
                //컬럼인덱스는 테이블 속성들의 순서넘버라고 보면 된다.
                String name = cursor.getString(1);
                int age = cursor.getInt(2);
                String major = cursor.getString(3);

                printLn(name + " / " + age + " / " + major);
            }

            cursor.close();
        }
    }

    private void updateData(String table_name, String name, int age, String major){
        if(sqLiteDatabase != null){
            printLn("데이터 수정 완료");
            String query = "update " + table_name + " set age=?, major=? where name=?;";
            Object[] params = new Object[]{age, major, name};

            sqLiteDatabase.execSQL(query, params);
        }
    }

    public void printLn(String text){
        tv1.append(text + "\n");
    }
}

selectData 메소드에서 조회하는데 있어서 select * from 테이블네임 where name(속성명)="Amy" 이런식으로 특정 데이터를 뽑아낼 수 있다.

* 은 이 테이블의 전체 데이터를 뽑아달라는 의미이고, where 이후에 조건을 설정해주는 것이다.

 

결과

 

 

Device File Explorer에 들어가서 /data/data/패키지명/databases 로 들어가면 데이터베이스가 만들어진 것을 볼 수 있다.(디폴트)

 

이렇게 데이터베이스를 만들고 조회, 업데이트도 해보았다. 그런데 테이블의 속성을 추가 or 삭제하고 싶거나 여러모로 테이블에 변형을 주고 싶을 경우 삭제하고 다시 만들면 제일 간단하지만, 앱이 서비스 중이면 사용자들의 데이터가 사라질 수 있다. 그래서 데이터베이스 버전을 관리할 수 있는 SQLiteOpenHelper를 사용해 볼 것이다.

 

주요 메소드

 

1. SQLiteOpenHelper를 상속하면 오버라이드 하는 메소드

  • onCreate(): 데이터베이스가 처음 생성될 때 호출 (필수 정의)
  • onUpgrade(): 버전이 바뀌어서 업그레이드 되었을 경우 호출 (필수 정의)
  • onOpen(): 버전과 상관없이 실행 (필수 정의 아님)

2. 그 외

  • getReadableDatabase(): SQLiteDatabase 객체를 반환하는데 보통 select 할 때 사용
  • getWritableDatabase(): 마찬가지로 SQLiteDatabase 객체 반환, 데이터베이스에 무언가 적용시킬 때(insert, delete, update) 사용

위에 1번에서 언급한 것과 같이 SQLiteOpenHelper를 상속하는 클래스를 하나 만들고 그 안에 1번 메소드들을 오버라이드 해준다.

그리고 getWriableDatabases()나 getReadableDatabase()는 DB파일을 만들 때나 데이터를 읽어볼 때나 쓸 때 무언가 일을 할 때 호출하고 SQLiteDatabase 객체를 반환한다.

SQLiteDatabase은 DB가 만들어지고 업그레이드가 필요할 때 콜백 메소드가 호출된다는 점인데 여러 가지 상태에 따른 콜백 메소드를 다시 정의하면 상태에 맞는 처리가 가능하다. 

 

 

코드

 

activity_main.xml

<?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">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="DB, Table 생성"
            android:id="@+id/button1"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext1_1"
            android:hint="DB명"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext1_2"
            android:hint="테이블명"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="데이터 입력"
            android:id="@+id/button2"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext2_1"
            android:hint="이름"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext2_2"
            android:hint="나이"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext2_3"
            android:hint="전공"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext2_4"
            android:enabled="false"
            android:hint="순위"/>


    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="데이터 수정"
            android:id="@+id/button3"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext3_1"
            android:hint="이름"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext3_2"
            android:hint="나이"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext3_3"
            android:hint="전공"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext3_4"
            android:enabled="false"
            android:hint="순위"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="데이터 삭제"
            android:id="@+id/button5"/>

        <EditText
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:id="@+id/edittext5"
            android:hint="이름"/>

    </LinearLayout>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="데이터 조회"
        android:id="@+id/button4"/>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/textview1"
                android:textSize="20dp"/>

        </LinearLayout>
    </ScrollView>


</LinearLayout>

 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    Button b1,b2,b3,b4,b5;
    TextView tv1;
    EditText et1_1, et1_2, et2_1, et2_2, et2_3, et2_4, et3_1, et3_2, et3_3, et3_4, et5;

    Helper helper;
    SQLiteDatabase sqLiteDatabase;
    String database_name, table_name;

    boolean up = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        b1 = findViewById(R.id.button1);
        b2 = findViewById(R.id.button2);
        b3 = findViewById(R.id.button3);
        b4 = findViewById(R.id.button4);
        b5 = findViewById(R.id.button5);

        tv1 = findViewById(R.id.textview1);

        et1_1 = findViewById(R.id.edittext1_1);
        et1_2 = findViewById(R.id.edittext1_2);
        et2_1 = findViewById(R.id.edittext2_1);
        et2_2 = findViewById(R.id.edittext2_2);
        et2_3 = findViewById(R.id.edittext2_3);
        et2_4 = findViewById(R.id.edittext2_4);
        et3_1 = findViewById(R.id.edittext3_1);
        et3_2 = findViewById(R.id.edittext3_2);
        et3_3 = findViewById(R.id.edittext3_3);
        et3_4 = findViewById(R.id.edittext3_4);
        et5 = findViewById(R.id.edittext5);

	//DB 생성 버튼
        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                table_name = et1_2.getText().toString();
                database_name = et1_1.getText().toString();
                helper = new Helper(getApplicationContext(), database_name, null, 1); //생성자 맞춰 helper 객체 변수 생성
                sqLiteDatabase = helper.getWritableDatabase(); //DB 생성 호출 -> 버전 업그레이드가 아니라면 onCreate()가 실행될 것 이다.

            }
        });

	//데이터 입력 버튼
        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    if(up == false) { //업그레이드 전
                        String name = et2_1.getText().toString();
                        String age = et2_2.getText().toString();
                        String major = et2_3.getText().toString();
                        insertData(table_name, name, Integer.parseInt(age), major, -1); //입력 메소드 호출

                    }
                    else if(up == true){ //업그레이드 후
                        String name = et2_1.getText().toString();
                        String age = et2_2.getText().toString();
                        String major = et2_3.getText().toString();
                        String rank = et2_4.getText().toString();
                        insertData(table_name, name, Integer.parseInt(age), major, Integer.parseInt(rank)); //입력 메소드 호출
                    }
                }catch (Exception e){
                    printLn("입력 오류");
                }
            }
        });
	
    	//데이터 수정 버튼
        b3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    if(up == false) {
                        String name = et3_1.getText().toString();
                        String age = et3_2.getText().toString();
                        String major = et3_3.getText().toString();
                        updateData(table_name, name, Integer.parseInt(age),major, -1); //수정 메소드 호출

                    }
                    else if(up == true){
                        String name = et3_1.getText().toString();
                        String age = et3_2.getText().toString();
                        String major = et3_3.getText().toString();
                        String rank = et3_4.getText().toString();
                        updateData(table_name, name, Integer.parseInt(age),major, Integer.parseInt(rank)); //수정 메소드 호출
                    }
                }catch (Exception e){
                    printLn("입력 오류");
                }
            }
        });

	//데이터 삭제 버튼
        b5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = et5.getText().toString();
                deleteData(table_name, name); //삭제 메소드 호출
            }
        });

	//데이터 조회 버튼
        b4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                    selectData(table_name); //조회 메소드 호출
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

    }

    private void insertData(String table_name, String name, int age, String major, int rank){
        printLn("데이터 입력 완료");

        //입력 쿼리
        if(up == false) {
            String query = "insert into " + table_name + "(name, age, major) VALUES(?, ?, ?);";
            Object[] params = new Object[]{name, age, major};
            sqLiteDatabase = helper.getWritableDatabase();
            sqLiteDatabase.execSQL(query, params);
        }
        else if(up == true){
            String query = "insert into " + table_name + "(name, age, major, rank) VALUES(?, ?, ?, ?);";
            Object[] params = new Object[]{name, age, major, rank};
            sqLiteDatabase = helper.getWritableDatabase(); //객체 반환해서 지정해주고
            sqLiteDatabase.execSQL(query, params); //실행
        }

    }

    private void updateData(String table_name, String name, int age, String major, int rank){
        printLn("데이터 수정 완료");

        //업데이트 쿼리
        if(up == false) {
            String query = "update " + table_name + " set age=?, major=? where name=?;";
            Object[] params = new Object[]{age, major, name};
            sqLiteDatabase = helper.getWritableDatabase();
            sqLiteDatabase.execSQL(query, params);
        }
        else if(up == true){
            String query = "update " + table_name + " set age=?, major=?, rank=? where name=?;";
            Object[] params = new Object[]{age, major, rank, name};
            sqLiteDatabase = helper.getWritableDatabase();
            sqLiteDatabase.execSQL(query, params);
        }
    }

    private void deleteData(String table_name, String name){
        printLn("데이터 삭제 완료");

        //삭제 쿼리
        String query = "delete from " + table_name + " where name=?;";
        Object[] params = new Object[]{name};
        sqLiteDatabase = helper.getWritableDatabase();
        sqLiteDatabase.execSQL(query, params);
    }

    private void selectData(String table_name){
        printLn("데이터 조회");

        sqLiteDatabase = helper.getReadableDatabase();

        //조회 쿼리
        String query = "select * from " + table_name + ";";
        Cursor cursor = sqLiteDatabase.rawQuery(query,null);

        if(up == false) {
            for (int i = 0; i < cursor.getCount(); i++) {
                cursor.moveToNext();
                String name = cursor.getString(1);
                int age = cursor.getInt(2);
                String major = cursor.getString(3);

                printLn(name + " / " + age + " / " + major);
            }
        }
        else if(up == true){
            for (int i = 0; i < cursor.getCount(); i++) {
                cursor.moveToNext();
                String name = cursor.getString(1);
                int age = cursor.getInt(2);
                String major = cursor.getString(3);
                int rank = cursor.getInt(4);

                printLn(name + " / " + age + " / " + major + " / " + rank);
            }
        }

        cursor.close();

    }

    private class Helper extends SQLiteOpenHelper{

        public Helper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }

        //DB를 최초 생성할 때 호출
        @Override
        public void onCreate(SQLiteDatabase db) {
            printLn("onCreate()");
            
            //데이터베이스 최초 생성 쿼리
            String query = "create table " + table_name +"(id integer primary key autoincrement, name text, age integer, major text)";
            db.execSQL(query);

            printLn("데이터베이스 및 테이블 생성됨");

        }

        //업그레이드 되었을 경우 호출
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            printLn("onUpgrade()");
            printLn(database_name + " / " + table_name + "이전버전: "+oldVersion + " 새로운버전: "+newVersion);

            String query = "alter table " + table_name + " add column rank integer null;"; //rank라는 칼럼(속성) 하나를 추가해줬다.
            db.execSQL(query);
            
            et2_4.setEnabled(true);
            et3_4.setEnabled(true);
            up = true;

            printLn("새로운 버전으로 업그레이드 완료");

        }
        
        @Override
        public void onOpen(SQLiteDatabase db) {
            super.onOpen(db);
            printLn("onOpen()");
        }
    }

    private void printLn(String text){
        tv1.append(text + "\n");
    }
}

 

결과

 

version을 1로 두고 최초 DB를 생성하였다.

TextView에 찍힌 것을 잘 보면 순서가 어떻게 됐는지 알 수 있다.

버전 업데이트 전이라 순위 입력은 불가능하다.

 

업그레이드가 된 후 모습이다. alter문으로 컬럼을 하나 추가해줬기 때문에 순위 입력도 가능해졌다.

 

 

부족한 점, 피드백 환영합니다.

 

감사합니다.

 

 

참고

정재곤, 『Do it! 안드로이드 앱 프로그래밍 - 개정 6판』, 이지스퍼블리싱(주)