반응형

안녕하세요, 츄르 사려고 코딩하는 집사 코집사입니다.


이번 포스팅 주제는 안드로이드 스튜디오에서 SQLite를 이용한 DB 추가, 삭제, 조회 등을 가진 것을 만들다가 생긴 에러를 잡아서 문제 해결로 올리려고 합니다. 진짜 이 문제 때문에, 2일 정도 넘게 시간을 잡아먹었네요...ㅠ


제가 하려고 했던 것은, 라디오 버튼(Radio button)에서 값을 받아와 DB에 저장하려고 했습니다.

그래서, 열심히 작업을 했었죠. 

라디오 그룹에서 체크된 라디오 버튼을 찾아서 그 ID를 변수에 저장을 하고, 그 변수를 DB에 저장하려고 하는 순간 아래와 같은 오류를 Logcat에서 찾았습니다.



DB 구성은 다음과 같이 했었습니다.

"CREATE TABLE person (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, memo TEXT, priority INTEGER);");


근데, _id는 컬럼으로 들어가지 않더라구요. id는 자동적으로 DB에 데이터가 들어오면 증가하게 되었습니다.

그래서, 데이터를 넣을 때 다음과 같이 sql를 짰습니다.

sql = String.format("INSERT INTO person VALUES(NULL, '"+name+"','"+memo+"',"+check+");");


그랬더니 아래와 같은 문제가 발생했습니다. App을 실행하니 App이 자꾸 종료가 됐습니다.


Caused by: android.database.sqlite.SQLiteException: table person has 3 columns but 4 values were supplied (code 1): , while compiling: INSERT INTO person VALUES(NULL,'Name','Name','1');


person이라는 table에 3개의 컬럼을 가지고 있는데 4개의 변수 값을 넣었다고 에러가 뜬겁니다. 

그래서, 아 NULL을 넣어서 그런거구나... 생각을 하고 NULL을 지웠습니다.


sql = String.format("INSERT INTO person VALUES('"+name+"','"+memo+"',"+check+");");


그랬더니, 이제는 아래와 같은 에러가 발생했습니다.


    Error Code : 20 (SQLITE_MISMATCH)

    Caused By : Data type mismatch.

    (datatype mismatch (code 20))


데이터 타입이 맞지 않다고.... 오류가 떴습니다. 근데 아무리 생각을 해도 데이터 타입도 다 맞추고 했는데 뭔가 이상하더라구요. priority 라는 변수를 지우고 name과 memo만 이루어진 컬럼에 _id 로 테이블로 구성을 시켜서 했습니다. 근데 잘 넣어지는 겁니다. 


App에서 작동을 추가를 해보고 지우고 조회를 해봤습니다.

지울 땐 DELETE FROM person으로 person 테이블에 있는 모든 row를 다 지웠는데 _id는 그대로 남아있더라구요

즉, 아래와 같이 테이블이 구성됐습니다.


_id    name memo

1

2

3

4

5

6


_id는 지워지지 않고, name과 memo column만 지워져서 뭔가 많은 생각이 떠오르더라구요.


저 _id가 문제가 있겠다.. 라고 생각을 해서 오픈 채팅방에 물어도 보고, 현직자에게도 물어 봤는데도 이런 상황을 처음 겪어봤다라고 하더라구요. 진짜 2일동안 삽질을 한 결과 결국엔 해결을 했습니다!


해결 방법으로는 너무 간단해서 성취감보단 허탈함이 더 컸습니다.


해결 방법 : _id를 가진 table을 지우고 새로운 table을 만들었더니 해결....


왜 이 생각을 못했는지 모르겠네요....

뭐가 안된다고 하면 컴퓨터를 껐다가 키면 다 됐었는데 똑같은 방법으로 했으면 됐을텐데.. 계속 이 생각만 했습니다.


이것과 관련된 문제가 구글이나 다음, 네이버에는 찾아봐도 없어서 눈물날 뻔 했지만, 그래도 해결을 할 수 있어서 좋았고, 다른 공부하는 분들도 저와 같은 문제가 발생하면 이 글을 보고 꼭 해결했으면 좋겠습니다.

마지막으로, 완료된 화면과 코드를 올려드리겠습니다.



-2019년 1월 18일 금요일 내용 추가합니다.-


버전 업을 해서 DB에 컬럼들을 수정하면 해결할 수도 있을 것 같습니다.




<MainActivity.java>

package com.example.myyou.ttt;


import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

EditText nameEdit;
EditText memoEdit;
TextView result;
DBHelper dbHelper;

final static String dbName = "yg.db";
final static int dbVersion = 1;

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


nameEdit = (EditText)findViewById(R.id.nameedit);
memoEdit = (EditText)findViewById(R.id.memoedit);
result = (TextView)findViewById(R.id.result);
dbHelper = new DBHelper(this, dbName, null, dbVersion);

}


public void mOnClick(View v){
SQLiteDatabase db;
String sql;


switch (v.getId()) {
case R.id.insert: //추가 버튼(insert)
RadioGroup rg = (RadioGroup)findViewById(R.id.radiogroup);
String name = nameEdit.getText().toString();
String memo = memoEdit.getText().toString();
int check = rg.getCheckedRadioButtonId();
RadioButton rd = (RadioButton)findViewById(rg.getCheckedRadioButtonId());
//String radiovalue = check.getText().toString();

//String radiovalue = ((RadioButton)findViewById(rg.getCheckedRadioButtonId())).getText().toString();


//int id = rg.getCheckedRadioButtonId();
//RadioButton rb = (RadioButton)findViewById(id);
//Toast.makeText(MainActivity.this,rb.getText(),Toast.LENGTH_SHORT).show();

db = dbHelper.getWritableDatabase();
sql = String.format("INSERT INTO yg VALUES('"+name+"','"+memo+"',"+check+");");

db.execSQL(sql);
result.append("\nInsert Success");
break;

case R.id.delete: //전체삭제 버튼(delete)
db = dbHelper.getWritableDatabase();
sql = "DELETE FROM yg;";
db.execSQL(sql);
result.append("\nDelete Success");
break;


case R.id.select: //조회 버튼(select)
db = dbHelper.getReadableDatabase();
sql = "SELECT * FROM yg;";
Cursor cursor = db.rawQuery(sql, null);
if(cursor.getCount() > 0){
while(cursor.moveToNext()){
result.append(String.format("\n이름 = %s, 메모 = %s, 우선순위 = %s",
cursor.getString(0),cursor.getString(1),cursor.getString(2)));
}
}else{
result.append("\n조회결과가 없습니다.");
}
cursor.close();
break;
}
dbHelper.close();
}

class DBHelper extends SQLiteOpenHelper {

//생성자 - database 파일을 생성한다.
public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}

//DB 처음 만들때 호출. - 테이블 생성 등의 초기 처리.
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE yg (name TEXT, memo TEXT, priority INTEGER);");
result.append("\nyg 테이블 생성 완료.");
}

//DB 업그레이드 필요 시 호출. (version값에 따라 반응)
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS yg");
onCreate(db);
}

}
}


이상으로, 츄르 사려고 코딩하는 집사! 코집사였습니다.



반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기