【发布时间】:2015-11-05 16:14:59
【问题描述】:
我正在尝试从数据库中填充列表视图。当我尝试使用光标执行此操作时,出现错误:
android.database.sqlite.SQLiteException: no such column: _id (code 1): , while compile: SELECT _id FROM contacts WHERE _id ORDER BY name DESC
这是我的代码:
MainActivity.java
package com.boggs.barr.barrboggscontactlist;
import android.content.ContentValues;
import android.content.Loader;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
populateListView();
}
public static final String KEY_ID = "_id";
private void populateListView() {
String[] projection = {
KEY_ID
};
FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getApplicationContext());
SQLiteDatabase db = mDbHelper.getWritableDatabase();
String sortOrder =
FeedReaderContract.FeedEntry.COLUMN_NAME_NAME + " DESC";
Cursor cursor = db.query(
FeedReaderContract.FeedEntry.TABLE_NAME, // The table to query
projection, // The columns to return
KEY_ID, // The columns for the WHERE clause
null, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
String[] fromColumns = new String[] {FeedReaderContract.FeedEntry.COLUMN_NAME_NAME, FeedReaderContract.FeedEntry.COLUMN_NAME_PHONE};
int[] toViews = {R.id.name, R.id.phone};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
FeedReaderDbHelper.java
package com.boggs.barr.barrboggscontactlist;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.sql.RowId;
/**
* Created by adnroid developer site
*/
public class FeedReaderDbHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "FeedReader.db";
public static final String LONG_TYPE = " Long";
public static final String STRING_TYPE = " STRING";
public static final String BYTE_TYPE = " BYTE";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + FeedReaderContract.FeedEntry.TABLE_NAME + " (" +
FeedReaderContract.FeedEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
FeedReaderContract.FeedEntry.COLUMN_NAME_PICTURE + STRING_TYPE + COMMA_SEP +
FeedReaderContract.FeedEntry.COLUMN_NAME_NAME + STRING_TYPE + COMMA_SEP +
FeedReaderContract.FeedEntry.COLUMN_NAME_EMAIL + STRING_TYPE + COMMA_SEP +
FeedReaderContract.FeedEntry.COLUMN_NAME_PHONE + STRING_TYPE +
")";
private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + FeedReaderContract.FeedEntry.TABLE_NAME;
public FeedReaderDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// This database is only a cache for online data, so its upgrade policy is
// to simply to discard the data and start over
db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
FeedReaderContract.java
package com.boggs.barr.barrboggscontactlist;
import android.provider.BaseColumns;
import android.support.annotation.Nullable;
/**
* Created by android developer site.
* attempted to do database ran out of time
*/
public final class FeedReaderContract {
// To prevent someone from accidentally instantiating the contract class,
// give it an empty constructor.
public FeedReaderContract() {}
/* Inner class that defines the table contents */
public static abstract class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "contacts";
public static final String _ID = "_id";
public static final String COLUMN_NAME_PICTURE = "picture";
public static final String COLUMN_NAME_NAME = "name";
public static final String COLUMN_NAME_EMAIL = "email";
public static final String COLUMN_NAME_PHONE = "phone";
public static final Nullable COLUMN_NAME_NULLABLE = null;
}
}
我读过我需要将 ID 传递给光标?但我不确定这意味着什么。对我来说它应该可以工作,因为我将 ID 包含在要包含在光标中的列列表中。任何帮助表示赞赏!
编辑:我问这个是因为有同样问题的人提出的解决方案对我不起作用。他们一直建议尝试使用 RowId 或 .moveToFirst 来包含 ID。 Laalto 提出了一个对我有用的解决方案。
【问题讨论】:
-
如果您修改了架构,请卸载您的应用以重新创建数据库。
-
我如何知道我是否修改了架构?我要从模拟器中卸载应用程序吗?
-
如果你修改了
CREATE TABLE,那就是架构修改。 -
是否需要重启模拟器才能卸载?编辑:想通了如何卸载
-
不,不会这样做。以模拟器中的应用管理器为例。