2011-04-27 6 views
23

내가 실제 장치에 내 응용 프로그램을 디버깅하기 위해 노력하고있어하지만 난이 오류를 얻을 :java.lang.IllegalArgumentException가 '_id'가 존재하지 않는 열

ERROR/AndroidRuntime(981): Caused by: java.lang.IllegalArgumentException: column '_id' does not exist

내가 에뮬레이터에서 테스트하고있어, 오류가 나타나지 않습니다. 오류는 다음 코드의 마지막 줄에 주어진다 : 여기

adapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] { 
      DataHandlerDB.CONTACT_NAME_COL, 
      DataHandlerDB.CONTACT_NUMBER_COL, 
      DataHandlerDB.CONTACT_DURATION_COL, 
      DataHandlerDB.CONTACT_DATE_COL }, new int[] { 
      R.id.contact_name, R.id.phone_number, R.id.duration, R.id.date }); 

나의 활동 : 쿼리

public class MyActivity extends Activity { 

    private static final String LOG_TAG = "MyActivity"; 
    private ListView listview; 
    private SimpleCursorAdapter adapter;   
    private DataHandlerDB handler; 
    private SQLiteDatabase db; 
    private OpenHelper helper; 
    private Cursor c; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.main); 

     helper = new OpenHelper(this); 
     db = helper.getWritableDatabase(); 
     helper.onCreate(db); 
     setBasicContent(); 
     c.close(); 
    } 


    @Override 
    public void onDestroy(){ 

     super.onDestroy(); 
     DataHandlerDB.makeTheSelection(this).close(); 
     db.close(); 
     helper.close(); 

    } 

    @Override 
    public void onPause(){ 

     super.onPause(); 
     DataHandlerDB.makeTheSelection(this).close(); 
     db.close(); 
     helper.close(); 

    } 

    @Override 
    public void onStop(){ 

     super.onStop(); 
     DataHandlerDB.makeTheSelection(this).close(); 
     db.close(); 
     helper.close(); 

    } 


    @Override 
    protected void onResume(){ 

     super.onResume(); 
     setBasicContent(); 

    } 

    public void setBasicContent() { 

     listview = (ListView) findViewById(R.id.list_view); 

     Log.i(LOG_TAG, "listview " + listview); 

     c = DataHandlerDB.makeTheSelection(this); 

     c.moveToFirst(); 

     if(db.isOpen()) 
      Log.i(LOG_TAG, "db is opened"); 

     Log.i(LOG_TAG, "cursor: " + c.getCount()); 

     startManagingCursor(c); 

     adapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] { 
       DataHandlerDB.CONTACT_NAME_COL, 
       DataHandlerDB.CONTACT_NUMBER_COL, 
       DataHandlerDB.CONTACT_DURATION_COL, 
       DataHandlerDB.CONTACT_DATE_COL }, new int[] { 
       R.id.contact_name, R.id.phone_number, R.id.duration, R.id.date }); 

     Log.i(LOG_TAG, "before setAdapter"); 
     Toast.makeText(this, "Before setAdapter", Toast.LENGTH_SHORT).show(); 

     listview.setAdapter(adapter); 

     db.close(); 

     if(db.isOpen()){ 

      Log.i(LOG_TAG, "db is opened."); 

     } 

     if(!c.isClosed()){ 

      Log.i(LOG_TAG, "cursor is opened"); 

     }   
    }  
} 

기능과 Cursor 클래스 DataHandlerDB에 반환

public class DataHandlerDB { 

private static final String DATABASE_NAME = "calls.db"; 
private static final int DATABASE_VERSION = 1; 

protected static String CONTACT_NAME_COL = "contact_name"; 
protected static String CONTACT_NUMBER_COL = "contact_number"; 
protected static String CONTACT_DURATION_COL = "duration"; 
protected static String CONTACT_DATE_COL = "date"; 
protected static String CONTACT_MONTH_COL = "month"; 

// create the DB 
public static SQLiteDatabase createDB(Context ctx) { 
    OpenHelper helper = new OpenHelper(ctx); 
    SQLiteDatabase db = helper.getWritableDatabase(); 
    helper.onCreate(db); 
    helper.onOpen(db); 
    db.close(); 
    return db; 
} 

public static Cursor makeTheSelection(Context ctx) { 

    OpenHelper helper = new OpenHelper(ctx); 
    SQLiteDatabase db = helper.getWritableDatabase(); 

    Cursor cursor = db.query(TABLE_NAME_2, null, null, null, null, null, 
      "duration desc"); 

    cursor.moveToFirst(); 
    db.close(); 

    return cursor; 
} 
    // class OpenHelper 
public static class OpenHelper extends SQLiteOpenHelper { 

    private final Context mContext; 

    OpenHelper(Context context) { 

     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     this.mContext = context; 

    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     Log.i(LOG_TAG, "entrou no onCreate"); 
     String[] sql = mContext.getString(
       R.string.MyAppDatabase_OnCreate).split("\n"); 

     db.beginTransaction(); 

     try { 
      execMultipleSQL(db, sql); 
      db.setTransactionSuccessful(); 
     } catch (SQLException e) { 

      Log.e("Error creating tables and debug data", e.toString()); 
      throw e; 

     } finally { 
      db.endTransaction(); 

     } 
    } 

    private void execMultipleSQL(SQLiteDatabase db, String[] sql) { 

     for (String s : sql) { 

      if (s.trim().length() > 0) { 

       db.execSQL(s); 
      } 
     } 

    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 

     Log.w("MyDB Database", 
     "Upgrading database, this will drop tables and recreate."); 
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); 

    } 

    @Override 
    public void onOpen(SQLiteDatabase db) { 

     super.onOpen(db); 
    } 
} 
} 

다음은 SQL 명령이있는 XML 파일입니다.

<string name="MyAppDatabase_OnCreate"> 
    "CREATE TABLE IF NOT EXISTS contact_data(_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER, contact_name VARCHAR(50), number_type VARCHAR(50), contact_number VARCHAR(50), duration TIME, duration_sum TIME, date DATE, current_time TIME, cont INTEGER, type VARCHAR, month VARCHAR(50), day VARCHAR(50), year VARCHAR(50));" 
</string> 

응용 프로그램이 처음 시작할 때 데이터베이스를 만들지 않는다고 생각합니다. 나는 _id 컬럼을 찾을 수 있기 때문에 그렇게 생각한다.하지만 명시 적으로 XML 코드로 작성되어 _id 컬럼으로 생성된다. 나는 또한 _id을 포함하여 SELECT 메서드의 열을 명시 적으로 작성했기 때문에 그렇게 생각합니다.

Log.i(LOG_TAG, "Cursor(0)" + cursor.getColumnName(0)); 
: 나는과 같이 데이터베이스의 첫 번째 열을 로그인 한

Caused by: android.database.sqlite.SQLiteException: no such column: _id: , while compiling: SELECT _id, contact_id, contact_name, number_type, contact_number, duration, duration_sum, date, current_time, cont, type, month, day, year FROM contact_data ORDER BY duration desc

: 내가받을 오류가 거의 동일이 경우

Cursor cursor = db.query(TABLE_NAME_2, 
       new String[]{ 
       "_id", 
       "contact_id", 
       "contact_name", 
       "number_type", 
       "contact_number", 
       "duration", 
       "duration_sum", 
       "date", 
       "current_time", 
       "cont", "type", 
       "month", 
       "day", 
       "year"}, null, null, null, null, 
       "duration desc"); 

:이처럼했다

id이 아니라 _id이 인쇄되었습니다. 보시다시피, 성명서에는 _id이 기록되어 있습니다. 이 문제를 해결하는 방법에 대한 제안?

+0

기기에서 앱을 완전히 제거한 다음 (예 : 설정> 애플리케이션> 애플리케이션 관리) 다시 시도하십시오. 나는 당신의 데이터베이스가 이미'_id' 컬럼없이 존재했다고 의심합니다. – CommonsWare

+0

나는 당신이 말한대로했으나 오류는 계속 발생합니다. = ( – rogcg

답변

37

이 _id라는 열을 필요로하는 커서를 사용하려고합니다. 테이블 생성 문을 편집하고 _id라는 열을 추가하는 것만 큼 간단합니다.

_id INTEGER PRIMARY KEY AUTOINCREMENT 

이 추가하고 다음을 사용할 수 있습니다 :

그 declartion는 다음과 같이 보인다. SimpleCursorAdapter를 사용하려면이 요구 사항이 필요하다고 생각합니다.

UPDATE

"CREATE TABLE IF NOT EXISTS contact_data(_id INTEGER PRIMARY KEY AUTOINCREMENT, contact_id INTEGER, contact_name VARCHAR(50), number_type VARCHAR(50), contact_number VARCHAR(50), duration TIME, duration_sum TIME, date DATE, current_time TIME, cont INTEGER, type VARCHAR, month VARCHAR(50), day VARCHAR(50), year VARCHAR(50));" 

솔루션 : 나는 _ID 추가되지 않았기 때문에가 '('왼쪽 괄호 사이에 공백을 추가하고

+4

'CursorAdapter'에는 항상'_id'라는 열이 필요합니다. – surfer190

+1

별칭을 만들지 말고 사용할 수 있습니다! 이미 _id 열은 있지만 다른 이름이 있으면 SQL 쿼리에서 AS를 사용하여 기본 키 이름을 변경하면됩니다. {SELECT myprimarykey AS _id, 이름 테이블 이름 WHERE 'LIKE'% queryfilter % ';} – jcasadellaoller

9

내가 있었 비슷한 문제를 _ID 열을 프로젝션 인수에 추가해야하므로 _id을 projec에 추가하십시오. 쿼리의 인수가 해결책이었습니다.모든

String[] projections = {"_id", "name", "age"}; 

Cursor cursor = db.query(domainClass.getSimpleName(), projections, 
    null, null, null, null, null); 
+1

이것은 나를위한 해결책이었습니다 .. 감사합니다. –

2

먼저 응용 프로그램을 제거한 다음 할 다음 단계 :

  1. 청소
  2. 재 구축 프로젝트


    예 (는 @nobugs 댓글을 달았) 그는 프로젝트를

  3. 디버그 (Shift + F9)
관련 문제