2014년 5월 20일 화요일

[ Android ] SQLite 사용 방법

이번 튜토리얼에서는 SQLite를 사용하는 방법을 알아보도록 하겠습니다.

SQLite는 사용 가능한 자료형은 아래와 같이 5가지만 지원 합니다.

1. NULL
2. INTEGER : 1, 2, 3, 4, 6, 8 bytes의 정수 값
3. REAL : 8bytes의 부동 소수점 값
4. TEXT : UTF-8, UTF-16BE, UTF-16LE 인코딩의 문자열
5. BLOB : 입력 된 그대로 저장

그럼 이제부터 SQLite 사용 방법에 대하여 하나씩 알아보도록 하겠습니다.

1. SQLiteOpenHelper를 상속받은 기본 구조
 DBManager라는 새로운 클래스를 생성하고 SQLite를 사용하기 위해서 SQLiteOpenHelper를 상속 받았습니다. 그리고 아래와 같이 필수로 작성되어야 하는 함수가 존재합니다.

 DBManager() 함수는 생성자로 DB 이름과 버전을 넘겨 받습니다.

 onCreate() 함수는 생성자에서 넘겨받은 이름과 버전의 데이터베이스가 존재하지 않을때 한번 호출 됩니다. 그렇기 때문에 새로운 데이터베이스를 생성할때 사용하기에 알맞습니다.

 onUpgrade() 함수는 데이터베이스가 존재하지만 버전이 다르면 호출 됩니다. 데이터베이스를 변경하고 싶을때 버전을 올려주고 새로운 작업을 해주면 됩니다.


2. 데이터베이스 생성
 새로운 데이터베이스를 생성하고 제대로 생성이 되었는지 확인해 보겠습니다. 단말기를 사용해서 확인을 하려면 루팅을 해야하고 에뮬레이터를 사용하면 명령프롬프트를 사용해서 확인을 할 수 있습니다. 여기서는 두 방법을 사용하지 않고 DB를 검색하여 데이터가 제대로 들어 갔는지 확인해보겠습니다.

먼저 DB가 존재하지 않을때 아래와 같은 FOOD_LIST 테이블을 생성하도록 하겠습니다.

 FOOD_LIST 라는 테이블에 정수형, 기본 키 그리고 자동으로 값이 증가하는 _id 컬럼과, Text형식의 name 컬럼, 정수형 price 컬럼으로 구성 되도록 만들었습니다.


3. 삽입, 삭제, 갱신, 선택
 Xml에 코드를 작성하여 버튼과 에디트 텍스트를 만들고 삽입, 삭제, 갱신, 선택을 해보도록 하겠습니다.

main.xml

 기본 생성 된 main.xml에 테이블에 입력시킬 name과 price를 입력받는 EditText 두개, 쿼리 실행 후 테이블 안의 내용을 출력 할 TextView하나 그리고 삽입, 삭제, 갱신, 선택을 실행 할 Button 4개로 구성하였습니다.


MainActivity.java

 main.xml에서 선언해 주었던 위젯들을 연결하고 각 버튼을 누를때 DBManager로 쿼리를 요청하도록 되어있습니다.
 마지막 select 쿼리는 DBManager에 테이블의 모든 요소를 가져오도록 만들었습니다.


DBManager.java

 가장 핵심적인 부분이라고 할 수 있겠습니다.
 소스를 보시면 insert(), update(), delete() 함수의 내용이 똑같이 생겼는데요. 원래는 DBManager 이 소스에서 쿼리를 작성하려고 했는데 MainActivity.java에 작성을 하다보니 함수의 내용이 똑같아져 버렸습니다. 이쪽에다가 쿼리를 작성해 주는게 더 좋겠죠.

getReadableDatabase() : 읽기 가능, 사용 후 close()로 종료
getWritableDatabase() : 읽기, 쓰기 가능, 사용 후 close()로 종료

PrintData()함수를 보시면 삽입, 삭제, 갱신 쿼리를 요청 할 때는 execSQL() 함수를 사용 하지만 선택을 할 때는 rawQuery() 함수를 사용 하여야 합니다. select 쿼리는 결과값을 받아야 하기 때문에요.
 Cursor로 결과값을 받아서 moveToNext() 함수로 null이 나올때 까지 하나씩 이동해가면서 결과값에 접근합니다.
 값을 가져올때는 테이블을 생성할 때 속성 순서대로 0 부터 생성 된 속성까지 얻어 올 수 있습니다.


Select
 - select * from 테이블명;
    테이블의 모든 속성과 값을 가져온다.

 - select 속성, 속성... from 테이블명;
    테이블에 선택한 속성의 값만 가져온다.

Insert
 - insert into 테이블명 values(속성, 속성...);
   테이블에 입력한 속성값으로 추가 한다. (속성의 순서가 일치해야 함)

Delete
 - delete from 테이블명 where 조건, 조건...;
   테이블에 조건이 일치하는 값을 삭제한다.

Update
 - update 테이블명 set 값, 값... where 조건, 조건...;
   테이블에 조건에 일치하는 속성의 값을 입력한 값으로 변경한다.

쿼리문에 조건은 콤마(,) 사용 시 여러 조건을 가질 수 있습니다.

기본적인 SQLite 사용방법 튜토리얼은 여기까지 입니다.

위 소스에는 예외처리가 안되어있습니다.






댓글 33개:

  1. 작성자가 댓글을 삭제했습니다.

    답글삭제
  2. 안녕하세요 안드로이드를 막 배우고 있는 초보 학생입니다.. 질문 하나만 드려도 될까요
    S
    QLite 에서 Select로 테이블에 있는 값을 가져오는것은 알겠는데..

    혹시 테이블에서 제가 필요한 값만 가져오게..
    위의 앱으로 보자면 "배" 를 입력하고 select를 누를시 가격 700 원이
    텍스트에 뜨도록 하고싶은데 혹시 이건 어떻게 해야하나요?

    답글삭제
    답글
    1. Select 구문을 사용할때 아래와 같이 사용이 가능합니다.

      (해당 조건의 모든 필드값을 가져올때) select * from 테이블명 where 조건;

      (해당 조건의 원하는 필드만 가져올때) select 필드명 from 테이블명 where 조건;

      아래와 같이 하시면 될 것 같습니다.

      select price from 테이블명 where foodName='배';

      삭제
  3. 죄송한데 복사 붙여넣기햇는데 작동이 중지되었습니다라고뜨는데 어떻해야되죠?

    답글삭제
    답글
    1. 저도 이 분과 같습니다. 어떻게 해결해야 하죠?ㅜ

      삭제
    2. 로그캣을 통하여 어떤 오류가 출력되는지 확인이 필요할 것 같습니다.

      삭제
    3. xml 레이아웃 파일의 대소문자 문제로 사료됩니다.
      linearlayout -> LinearLayout
      textview -> TextView
      로 수정해보시고, 그래도 안되면 다시 로그캣 확인해보세요.

      삭제
  4. 안녕하세요 초보 개발자 입니다. ^^
    다름이 아니라 블러그에 올리신 소스코드 어떤 툴을 이용하셨나요
    너무 보기 좋은데.. 저도 소스 블러그 관리를 해보고 싶어서요 ^^
    사이트나 프로그램 이름좀 가르쳐 주실수 있으신지요ㅗ ^^

    답글삭제
    답글
    1. http://berabue.blogspot.kr/2014/04/syntaxhighlighter_29.html

      위 포스팅을 보시면 될것 같습니다 ^^

      삭제
  5. 안녕하세요 취미 개발자입니다 ^^
    저는 숫자를 입력하면 콤마표시가 되도록 했는데요. 예를 들면 2000000 입력시 2,000,000 이렇게 됩니다.
    그런데 이것을 저장하려고 하니 1개의 value가 아니라 3개의 value로 인식하더군요 ㅠ
    형식을 text, money, blob 다 해봐도 ㅠㅠ 1개가 아니라 3개로 인식합니다. ㅠ 어찌해야 될까요??

    답글삭제
    답글
    1. 숫자로 저장하시려면 콤마를 제거하셔야 할테구요. 문자로 저장하시려면 콤마는 구분자로 사용되기 때문에 따옴표를 이용하셔야 할 것 같습니다.
      예를 들면 '2,000,000', '변수' 이런식으로 넣어주시면 될것같습니다.

      삭제
  6. Insert
    - insert info 테이블명 values(속성, 속성...);

    info가 아니라 into가 맞지 않을까요?! 오타인듯합니다.

    답글삭제
  7. 와우..아직 실행해보진 않았지만 차근차근 읽어가면서 따라 써봤어요 !
    후..제가 2시간이 넘게 sqlite관련 강의, 자료를 찾아봤는데. 이렇게 상세하고 전체적인 이해가
    쉽게가도록 설명해 주신분은 처음입니다. 감사합니다.

    답글삭제
  8. 실행은 정상으로 됐습니다. 삽입, 삭제다 되구요!
    딱하나 안되는건 업데이트 부분이었습니다. 소스는 똑같이 썼구용! 왜그런지 계속보고이써요 ㅠㅠ

    그리고 궁금한게 있는데 입력없이 삽입할 때에 시스템오류로 앱이 꺼지는데
    그래서 .. 예외처리부분을 좀 알고싶어요!
    자바공부할때 예외처리를 공부했는데, 안드로이드 db부분에서는 어떻게 작성해 줘야할지 모르겠습니다 ㅠ.

    답글삭제
    답글
    1. 아아 예외처리는 해결해써요!!
      업데이트만 ..ㅠ.ㅠ

      삭제
  9. 글 잘보고 있습니다. 코드 똑같이 따라하고 있는데,
    메인 onCreate에서 널 에러가 생기는데 혹시 이유를 알 수있을까요?

    답글삭제
    답글
    1. 에러 로그를 알려주시면 짐작해볼 수 있을것 같습니다!

      삭제
    2. Process: com.example.ksk_mac.test_maker, PID: 17294
      java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ksk_mac.test_maker/com.example.ksk_mac.test_maker.Test2}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2378)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440)
      at android.app.ActivityThread.access$800(ActivityThread.java:162)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:135)
      at android.app.ActivityThread.main(ActivityThread.java:5422)
      at java.lang.reflect.Method.invoke(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:372)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
      Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
      at com.example.ksk_mac.test_maker.Test2.onCreate(Test2.java:30)
      at android.app.Activity.performCreate(Activity.java:6057)
      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2331)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440) 
      at android.app.ActivityThread.access$800(ActivityThread.java:162) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:135) 
      at android.app.ActivityThread.main(ActivityThread.java:5422) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:372) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707) 
      이런식으로 logcat이 나옵니다 ㅠㅠ

      삭제
    3. Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
      at com.example.ksk_mac.test_maker.Test2.onCreate(Test2.java:30)

      Test2.java 소스의 30번 라인에 NULL 오류가 발생하고 있습니다.

      해당 라인에 존재하는 변수가 정상적인 변수인지 확인해보시면 될것같습니다.

      삭제
  10. 안녕하세요, 자료 잘 보고 갑니다.
    한 가지 여쭤볼게 있는데요, (2)에서 테이블을 생성하고 (3) MainActivity.java에서 'Food.db'가 갑자기 등장하던데, db명은 언제 정해진건가요? 그리고 타 앱에서도 db에 접근할 수 있나요? 감사합니다

    답글삭제
  11. 안녕하세요 잘봤습니다. 그런데 이런 작업전에 SQLite를 설치 해야 되죠? 설치만하고 이리 코딩하면되나요?

    답글삭제
  12. 안녕하세요 초보개발자입니다 영단어장을 만들어 보려고 하는데 단어마다 이미지를 연관시켜서 만들생각인데
    SQLite 에 이미지를 넣으면 비효율 적인가요?

    답글삭제
  13. 안녕하세요, 답변 달릴지는 모르겠지만 그래도 질문 납깁니다.
    휴대폰 정보를 저장하고 싶은데 integer를 사용하면 휴대폰 제일 앞자리 010 에서
    0이 지워진 상태로 저장이 됩니다.
    그리고 11자리의 숫자부터 이상하게 저장이 되는데, 해결방법이 무엇인가요?

    답글삭제
    답글
    1. 우선 Integer 타입을 사용하시면 앞자리 0은 자동으로 제외됩니다.
      숫자를 표기할때 앞자리에 0이 오는 경우가 없기 때문입니다.

      그리고 11자리의 숫자부터 값이 이상하게 저장되는 이유는 Integer 자료형의 범위가
      –2,147,483,648 ~ 2,147,483,647 이기 때문에 최대 10자리까지 정상적인 표현이 가능합니다.

      휴대폰 앞자리를 0으로 표현하고 싶으신 경우에는 정수형 자료형이 아닌 문자형 자료형을 선택하셔야하고, 11자리 이상의 값을 표현하고 싶으신 경우에는 int 보다 큰 자료형을 사용하셔야 합니다.

      삭제
  14. 0-17 10:51:58.229 26142-26142/com.example.porg37.jointest E/SQLiteLog: (1) near "', 유앤아이'": syntax error
    10-17 10:51:58.244 26142-26142/com.example.porg37.jointest E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.porg37.jointest, PID: 26142
    android.database.sqlite.SQLiteException: near "', 유앤아이'": syntax error (code 1): , while compiling: insert into Volunteer values(null, 'you@and.i', aws12', 유앤아이', 01012345678', 도보);
    #################################################################
    Error Code : 1 (SQLITE_ERROR)
    Caused By : SQL(query) error or missing database.
    (near "', 유앤아이'": syntax error (code 1): , while compiling: insert into Volunteer values(null, 'you@and.i', aws12', 유앤아이', 01012345678', 도보);)
    #################################################################

    -------------------------------------------------------------------
    이런 오류가 뜨는데.. 무엇이 잘못일까요..T^T

    답글삭제
  15. 작성자가 댓글을 삭제했습니다.

    답글삭제
  16. 안녕하세요 코드 잘 보았습니다!
    그런데 궁금한게 있어서 덧글을 남깁니다.

    별거는 아니고 DBManager를 만들때
    insert, update, delete를 정의할 때 매개변수로 _query String을 사용하셨는데
    어떻게 이름을 지어도 상관은 없겠지만, 언더스코어(_)를 붙이시는 이유가 궁금해요

    답글삭제
    답글
    1. 프로젝트 진행시 코드 작성 규칙이 없을때 사용하는 저만의 변수 명명 방법 입니다.

      매개변수앞에 언더바를 붙여 해당 함수 내에서 매개변수인지 함수에서 선언한 지역변수인지 구분을 위해 사용중입니다.

      예약어 중에 앞에 언더바가 붙는 경우가 있어 사용되지 않는 방식입니다.

      삭제
  17. 혹시 foodname에 포도를 치면 포도의 이름을 가진 정보들만 나오게끔 어떻게 하나요?

    답글삭제
    답글
    1. // Select2
      Button btnSelect2 = (Button) findViewById(R.id.select2);
      btnSelect2.setOnClickListener(new View.OnClickListener() {

      @Override
      public void onClick(View v) {
      String name = etName.getText().toString();
      dbManager.select("select * from MANAGEMENT_LIST where name = '" + name + "';");
      tvResult.setText( dbManager.PrintData() );
      }
      });

      이렇게 적었는데 되지않네여...오류뜹니다 ㅠㅠ

      삭제
  18. 아무것도 입력안하고 insert를 누르면 작동이 중지 되었습니다.라고 뜨는데 원래 그런건가요?

    답글삭제
  19. 안드로이드 스튜디오에서 작업을 하고 블루스텍으로 확인을 하는데 모양 틀은 나오지만 동작은 구동이 되지않습니다. ㅠㅠ xml에서 작업한것은 나오지만 java쪽에서 작업한것은 안되는거 같아요~~ 문제를 모르겠습니다.

    답글삭제

Post List