android - SQLite异常: no such column: _id: for ContentProvider

标签 android sqlite android-contentprovider

我在 SQLite 上运行的 ContentProvider 中声明了 _ID 自动增量列,但在堆栈跟踪中收到以下“no such column: _id”错误消息,如何修复此错误?

 FATAL EXCEPTION: AsyncTask
 java.lang.RuntimeException: An error occured while executing doInBackground()
 Caused by: android.database.sqlite.SQLiteException: no such column: _id:,
 while compiling: SELECT _id, title, text FROM notes

另一个奇怪的事情是,我没有在代码中的任何地方调用 contentProvider 类的查询方法,但是如果 ContentProvider 的查询,我在 ContentProvider 类的这个查询方法中以一行代码的形式得到了错误的位置方法没有被调用,那么它不应该出现在堆栈跟踪中,但是它确实存在,这里它告诉我堆栈跟踪中错误的位置

com.example.contentproviderexample.ProviderExample.query(ProviderExample.java:132)

ContentProvider 类 ProviderExample 第 132 行

Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);

编辑:在建议我从应用程序中卸载或删除数据并再次运行后,在我这样做之后,我从堆栈跟踪中得到了不同的错误,如下:

 Couldn't open notes.db for writing (will try read-only):
 android.database.sqlite.SQLiteException:
 AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY:
 , while compiling: CREATE TABLE IF NOT EXISTS
 notes (_id ID INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, text TEXT);

这里是ContentProvider类的完整查询方法

 @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(TABLE_NAME);
    qb.setProjectionMap(notesProjectionMap);
         switch(sUriMatcher.match(uri)){
         case NOTES:
             break;
         case NOTES_ID:
             selection = selection + "_id=" + uri.getLastPathSegment();
             break;
         default:
             throw new IllegalArgumentException("Unknown URI" + uri);    
         }
         SQLiteDatabase db = dbHelper.getReadableDatabase();
         Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder); // <-- no colunn _ID error here
         c.setNotificationUri(getContext().getContentResolver(), uri);
         return c

这里是 ProviderExample 类中扩展 ContentProvider 的更多代码

 public class ProviderExample extends ContentProvider {

public static final String DATABASE_NAME = "notes.db";
public static final int DATABASE_VERSION = 1;
public static final String TABLE_NAME = "notes";
public static final String AUTHORITY = "com.example.contentproviderexample.providerexample";
public static final UriMatcher sUriMatcher;
private static final int NOTES = 1;
private static final int NOTES_ID = 2;
private static HashMap<String, String> notesProjectionMap;

 static {
        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        sUriMatcher.addURI(AUTHORITY, TABLE_NAME, NOTES);
        sUriMatcher.addURI(AUTHORITY, TABLE_NAME + "/#", NOTES_ID);
    }

 public static interface NoteItems extends BaseColumns {

        // notes in the CONTENT_URI is often plural where the actual table name is often singular version of this word
        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes");
        public static final String _ID = "_id";
        public static final String TITLE = "title";
        public static final String TEXT = "text";
        public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.example.providerexample";
        // static final String SINGLE_RECORD = "vnd.android.cursor.item/vnd.example.providerexample";
        public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.example.providerexample";
        // static final String MULTIPLE_RECORDS = "vnd.android.cursor.dir/vnd.example.providerexample"; 
        public static final String[] PROJECTION_ALL = {_ID, TITLE, TEXT};
        public static final String SORT_ORDER_DEFAULT = TITLE + " ASC";

 }

 private static class DatabaseHelper extends SQLiteOpenHelper{

     DatabaseHelper(Context context){
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
     }

     @Override
     public void onCreate(SQLiteDatabase db) {
     db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + NoteItems._ID + " ID INTEGER PRIMARY KEY AUTOINCREMENT, " +  
             NoteItems.TITLE + " TEXT, " + NoteItems.TEXT + " TEXT);");
     }

     @Override
     public void onUpgrade(SQLiteDatabase db, int previousVersion, int newVersion) {
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
     onCreate(db);
     }

 }

private DatabaseHelper dbHelper;

@Override
public boolean onCreate() {
    dbHelper = new DatabaseHelper(getContext());
    return true;
}

@Override
public String getType(Uri uri) {
    switch (sUriMatcher.match(uri)){
        case NOTES:
            return NoteItems.CONTENT_TYPE;
        case NOTES_ID:
            return NoteItems.CONTENT_ITEM_TYPE;
        default:
            throw new IllegalArgumentException("Unknown URI" + uri);
    }

} 

这是 MainActivity 类

   public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor>{

private SimpleCursorAdapter adapter;
private LoaderManager loaderManager;
private CursorLoader cursorLoader;
private ListView listView;
private int primaryKey;
private String primaryKeyString;
private String testTitle;
private String testText;
private static final int LOADER_ID = 1;

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

    primaryKey = 0;
    testTitle = "test title";
    testText = "test text";

    ProviderExample providerExample = new ProviderExample();

    primaryKeyString = String.valueOf(primaryKey);
    getLoaderManager().initLoader(LOADER_ID, null, this);
    adapter = new SimpleCursorAdapter(this, R.layout.row_layout, null,
            new String[]{primaryKeyString, testTitle, testText}, new int[]{R.id.textView1, R.id.textView2, R.id.textView3},
            Adapter.NO_SELECTION);
    listView = (ListView) findViewById(R.id.listView1);
    listView.setAdapter(adapter);

    // load database with test values
    //loadDatabase();

}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String[] projection = {ProviderExample.NoteItems._ID, ProviderExample.NoteItems.TITLE, ProviderExample.NoteItems.TEXT };
    cursorLoader = new CursorLoader(this, ProviderExample.NoteItems.CONTENT_URI, projection, null, null, null);
    return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    adapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    adapter.swapCursor(null);
}
 }

最佳答案

我认为在创建表时您犯了一个错误。您已经在引号内给出了“ID ”,而且您还拥有 NoteItems._ID ,这使得“_id ID ”成为主要 ID。所以你可能需要纠正它..!!

 @Override
 public void onCreate(SQLiteDatabase db) {
 db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + NoteItems._ID + " ID INTEGER PRIMARY KEY AUTOINCREMENT, " +  
         NoteItems.TITLE + " TEXT, " + NoteItems.TEXT + " TEXT);");
 }

关于android - SQLite异常: no such column: _id: for ContentProvider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16556655/

相关文章:

android - Fragment Android 中的 GoogleApiClient

android - Room - 如何通过迁移首次显式创建所有表?

java - android SQLite,无法再在我的 listView 中查看数据

java - 更新 android mediastore 中的专辑封面?

Android:观察已删除线程的短信

android - 在 sharedpreference 中同时使用 apply() 和 commit()

c# - 从 ViewModel 到 View Xamarin 的 MVVMCross Calling 函数

android - Android Gradle Min SDK版本更改导致错误

r - 使用RSQLite时的R多行语句

php - 在 PHP 中使用 SQlite3 如何计算结果集中的行数?