안드로이드 SQLite 테이블 여러개 생성 - andeuloideu SQLite teibeul yeoleogae saengseong

모든 내용은 Do it! 안드로이드 앱 프로그래밍을 바탕으로 정리한 것입니다. 

모바일 데이터베이스

많은 양의 데이터를 체계적으로 관리하기 위해서 사용

(↔ SharedPreferences는 데이터를 간단하게 저장할 때!)

표준 SQL 문으로 데이터를 조회하는 관계형 DB를 단말에서 사용할 수 있다면 적은 양의 데이터라도 접근이 가능하므로 더 효율적!

SQLite

안드로이드는 임베디드 데이터베이스(Embedded Database)로 개발된 경량급 관계형 데이터 베이스 SQLite를 가짐

  • 파일로 만들어진 하위 수준의 구조를 가지면서 DB의 기능까지 그대로 사용할 수 있도록 만든 것
  • 저장될 때는 파일로 저장되므로 DB의 복사, 이동, 삭제가 매우 쉬움
  • 데이터 조회 속도가 빠름
  • 표준 SQL을 지원함
    • 기존의 웹이나 PC에서 사용하던 업무용 앱의 데이터 관리 기능을 그대로 사용할 수 있음
    • 원격 DB를 접근하는 SQL문을 로컬에서 똑같이 사용할 수 있음

∴ 앱의 개발 생산성↑, 향후 기능 변경에도 간단한 SQL 수정만으로 데이터 처리 방식을 바꿀 수 있음


데이터베이스와 테이블 생성

데이터베이스 ⊃ 테이블

데이터베이스는 여러 개의 테이블을 담는 그릇 → 우선 그릇을 만들거나 만들어진 그릇을 열고 닫을 수 있어야 함

public abstract SQLiteDatabase openOrCreateDatabase (String name, int mode, SQLiteDatabase.CursorFactory factory)
public abstract boolean deleteDatabase (String name)
public vodi execSQL (String sql) throws SQLException
  • openOrCreateDatabase() 메서드 : 데이터베이스를 만들거나 여는 메서드
    • 첫번째 파라미터 (String name) : 데이터베이스 이름 / 데이터베이스 파일명
    • 두번째 파라미터 (int mode) : 사용모드 - MODE_PRIVATE 상수
    • 세번째 파라미터 (factory) : 널(Null)이 아닌 객체를 지정할 경우, 쿼리의 결과 값으로 반환되는 데이터를 참조하는 커서를 만들어낼 수 있는 객체 전달
    • 반환되는 SQLiteDatabase 객체는 name 변수로 지정한 DB에 접근할 수 있는 메서드를 정의하고 있으므로, 해당 메서드로 DB를 열거나 만든 후에는 SQLiteDatabase 객체를 참조해야 함
...
    private void createDatabase(String name) {
        printText("createDatabase 호출");
        database = openOrCreateDatabase(name, MODE_PRIVATE, null);
        printText(name + " 데이터베이스 생성");
    }
...
  • deleteDatabase() 메서드 : 데이터베이스를 삭제하는 메서드
  • execSQL() 메서드 : 데이터베이스를 만들고 난 다음 SQL문을 실행할 때 사용하는 메서드
    • SQLiteDatabase 객체에서 가장 중요한 메서드 중 하나
    • 해당 메서드를 이용하여 테이블을 만들고, 레코드 추가와 같은 표준 SQL을 사용하는 여러 데이터 처리가 가능함
...
    database.execSQL("create table if not exists " + name + "("
                    + "_id integer PRIMARY KEY autoincrement,"
                    + " name text, "
                    + " age integer, "
                    + " mobile text);");
...
    database.execSQL("insert into " + tableName
                    + "(name, age, mobile)"
                    + " values "
                    + "('June', 20, '010-1234-1234' )");

헬퍼(Helper) 클래스

데이터베이스를 만드는 것 외에도 테이블의 정의가 바뀌어서 스키마(Schema)를 업그레이드할 필요가 있을 때 사용하는 클래스

스키마(Schema) 

  • 데이터베이스의 구조와 제약조건에 관해 전반적인 명세를 기술한 것
    • 속성(Attribute), 개체(Entity), 관계(Relation), 제약 조건들을 기술함
  • 테이블의 구조는 필요에 따라 바뀔 수 있음
  • ⚠ 테이블 안에 사용자가 저장한 데이터가 있는 경우, 그 데이터가 삭제되거나 수정되어야 할 수 있음
    • 스키마를 수정할 때는 테이블이 이미 사용되고 있는 상태인지 구별한 뒤에 처리해야 함

헬퍼 클래스를 사용하기 위해서는 SQLiteOpenHelper 클래스를 사용해야 함

SQLiteOpenHelper 클래스 - 데이터베이스를 만들거나 열기 위해 필요한 작업들을 도와주는 역할

public SQLiteOpenHelper (Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
  • 첫번째 파라미터 (Context context) : 액티비티 안에서 만들 경우 this로 지정할 수 있음
  • 두번째 파라미터 (String name) : 데이터 베이스의 이름
  • 세번째 파라미터 (factory) : 데이터 조회 시 반환하는 커서를 만들어 낼 CursorFactory 객체
  • 네번째 파라미터 (int version) : 데이터베이스 업그레이드를 위해 사용하며 기존에 생성되어 있는 데이터베이스 버전 정보와 다르게 지정하여 데이터베이스의 스키마나 데이터를 바꿀 수 있음

SQLiteOpenHelper 객체는 데이터베이스를 만들거나 열기 위해 필요한 작업을 도와주는 역할을 하지만, 

해당 객체를 만든다고 해서 데이터베이스 파일이 바로 만들어지는 것은 아님!

파일 생성을 위해서는 getReabableDatabase() 또는 getWritableDatabase() 메서드를 호출해야 함

→ 이 클래스의 장점은 데이터베이스가 만들어지거나 업그레이드할 때 콜백 메서드가 호출됨

→ 데이터베이스 생성, 업그레이드 등 여러 가지 상태에 따라 콜백 메서드를 다시 정의하면 각각의 상태에 맞게 처리할 수 있음

public abstract void onCreate (SQLiteDatabase db)
public abstract void onOpen (SQLiteDatabase db)
public abstract void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion)

DB 생성

DatabaseHelper.java

public class DatabaseHelper extends SQLiteOpenHelper {

    public static String NAME = "employee.db";
    public static int VERSION = 1;

    public DatabaseHelper(@Nullable Context context) {
        super(context, NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        // 데이터베이스 생성
        Log.d("DatabaseHelper", "onCreate 호출");

        String sql = "create table if not exists emp(" +
                " _id integer PRIMARY KEY autoincrement," +
                " name text," +
                " age integer," +
                " mobile text);";

        sqLiteDatabase.execSQL(sql);
    }

    @Override
    public void onOpen(SQLiteDatabase db) {
        // 데이터베이스 열 때 호출
        super.onOpen(db);
        Log.d("DatabaseHelper", "onOpen 호출");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int old, int recent) {
        // 데이터베이스 업그레이드
        Log.d("DatabaseHelper", "onUpgrade 호출 : " + old + " -> " + recent);

        if (recent > 1) {
            sqLiteDatabase.execSQL("DROP TABLE IF EXISTS emp");
        }
    }
}

MainActivity.java

    private void createDatabase(String name) {
        printText("createDatabase 호출");

        helper = new DatabaseHelper(this);
        database = helper.getWritableDatabase();  // 파일 생성

        printText(name + " 데이터베이스 생성");
    }

데이터 조회

데이터베이스를 열고 조회하는 방법에 대해 알아보기

  • rawQuery()
    • 데이터 조회를 위해 표준 SQL은 "SELECT ... "를 사용하는데, 이 구문을 통해 반환되는 Cursor 객체를 받기 위한 메소드
    • Cursor 객체는 테이블에 들어있는 각각의 레코드를 순서대로 접근할 수 있게 함
      • 이 객체는 처음에 아무런 레코드를 가리키지 않음
      • while 구문을 이용할 시, moveToNext() 메소드가 false 값을 반환할 때까지 레코드를 가져옴
      • for 구문을 이용할 시, getCount() 메소드를 이용해 전체 레코드 개수를 알아내어 moveToNext() 메소드 사용
  • Cursor는 사용한 후에 close() 메서드를 이용하여 닫아야 함
    public void executeQuery() {
        printText("executeQuery 호출");

        Cursor cursor = database.rawQuery("select _id, name, age, mobile from emp", null);
        int recordCount = cursor.getCount();
        printText("레코드 개수 : "+recordCount);

        for (int i = 0; i < recordCount; i++) {
            cursor.moveToNext();
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            int age = cursor.getInt(2);
            String mobile = cursor.getString(3);

            printText("레코드#"+ i + " : " + id + ", " + name + ", " + age + ", " + mobile);
        }
        cursor.close();
    }

[ API ]

칼럼에 대한 정보를 알아낼 수 있는 메서드

  • public abstract int getColumncount () : 칼럼의 전체 개수
  • public abstract int getColumnIndex (String columnName) : 칼럼의 이름을 통해 칼럼의 인덱스 확인
  • public abstract String getColumnName (int columnIndex) : 칼럼의 인텍스를 통해 칼럼의 이름을 확인
  • public abstract String[] getColumnNames () 

Cursor 관련 메서드

  • public abstract int getCount() : 레코드 개수
  • public abatract boolean moveToNext() : Cursor를 다음으로 이동
  • public abatract boolean moveToPrevious() : Cursor를 이전으로 이동
  • public abatract boolean moveToFirst() : Cursor를 맨 처음으로 이동
  • public abatract boolean moveToLast() : Cursor를 맨 마지막으로 이동
  • public abatract boolean move (int offset) : offset만큼 Cursor를 이동(음수는 이전, 양수는 다음으로)
안드로이드 SQLite 테이블 여러개 생성 - andeuloideu SQLite teibeul yeoleogae saengseong

⭐ 기억해야 할 순서!

(1) 데이터베이스 생성 → (2) 테이블 생성 → (3) 레코드 추가 → (3) 데이터 조회

다음 포스팅에서는 내용 제공자를 이용한 데이터 생성, 조회, 수정, 삭제에 대해 다루겠습니다!

* SharedPreferences에 대한 자세한 내용은 아래 포스팅 참고!

[Android] 간단한 값 저장은 SharedPreferences

모든 내용은 Do it! 안드로이드 앱 프로그래밍을 바탕으로 정리한 것입니다. SharedPreferences 앱 안에서 간단한 데이터를 저장하거나 복원할 때 사용 간단한 데이터를 저장해야 하는데 SQLite 같은 DB

junyoung-developer.tistory.com

안드로이드 SQLite 테이블 여러개 생성 - andeuloideu SQLite teibeul yeoleogae saengseong