2011-04-27 91 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列创建它。我也认为,因为我明确写了SELECT方法中的列,包括_id。我这样做是这样的:

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"); 

在这种情况下,我收到的错误几乎是一样的:

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

我登录数据库的第一列像这样:

Log.i(LOG_TAG, "Cursor(0)" + cursor.getColumnName(0)); 

它印上id,而不是_id。正如你所看到的,在陈述中写有_id。有关如何解决此问题的任何建议?

+0

从设备上完全卸载应用程序(例如,设置>应用程序>管理应用程序),然后重试。我怀疑你的数据库已经存在,没有'_id'列。 – CommonsWare 2011-04-27 23:56:46

+0

我照你说的做了,但错误依然存在。 =( – rogcg 2011-04-28 00:03:56

回答

37

您正在尝试使用需要的光标称为_id。就像编辑表创建语句并添加一个名为_id的列一样简单。

其declartion看起来是这样的:

_id INTEGER PRIMARY KEY AUTOINCREMENT 

添加这一点,那么你将能够使用它。我相信这是为了使用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 2015-06-15 14:04:37

+1

你可以使用别名而不是创建它!如果你已经拥有_id列但有其他名字,只需在你的sql查询中使用AS来更改你的主键名: {SELECT myprimarykey AS _id,name FROM TABLE WHERE name LIKE'%queryfilter%';} – jcasadellaoller 2016-04-21 15:17:03

9

我有类似的问题,因为我没有加入_id列到投影参数,因此将_id添加到投影查询的tions参数是解决方案。(评论说@nobugs


例子:

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

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

这是我的解决方案 傻了,谢谢。 – 2017-07-03 04:10:12

2

首先卸载该应用程序,然后执行以下步骤:

  1. 清洁项目
  2. 重建他的项目
  3. 调试应用程序(Shift + F9)
相关问题