Android sqlite 数据库报错 SQLiteException no such column

Posted

技术标签:

【中文标题】Android sqlite 数据库报错 SQLiteException no such column【英文标题】:Android sqlite database error SQLiteException no such column 【发布时间】:2012-08-02 19:25:24 【问题描述】:

当打开创建数据库的活动时,它立即崩溃并出现错误 SQLiteException: no such column。我不知道该怎么做,因为 SQLite 对我来说仍然是一个谜。

*新的错误,这次我可以创建锻炼记录,但是一旦我点击编辑它,我得到另一个不存在这样的列,这次是 squatLabel。但它确实存在....*

编辑:此时我得到的唯一错误是不存在这样的列:squatLabel

import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.AdapterView.AdapterContextMenuInfo;

public class WorkoutList extends ListActivity 
    private static final int ACTIVITY_CREATE=0;
    private static final int ACTIVITY_EDIT=1;

    private static final int INSERT_ID = Menu.FIRST;
    private static final int DELETE_ID = Menu.FIRST + 1;

    private StrongDbAdapter mDbHelper;


    /** Called when the 5x5 button is pressed in first activity */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.workout_list);
        mDbHelper = new StrongDbAdapter(this);
        mDbHelper.open();
        fillData();
        registerForContextMenu(getListView());
    

    private void fillData() 
        Cursor NotesCursor = mDbHelper.fetchAllNotes();

        // Get all of the rows from the database and create the item list
        NotesCursor = mDbHelper.fetchAllNotes();
        startManagingCursor(NotesCursor);

        // Create an array to specify the fields we want to display in the list (only TITLE)
        String[] from = new String[]StrongDbAdapter.KEY_TITLE,;

        // and an array of the fields we want to bind those fields to (in this case just text1)
        int[] to = new int[]R.id.workout_row ;

        // Now create a simple cursor adapter and set it to display
        SimpleCursorAdapter notes = 
            new SimpleCursorAdapter(this, R.layout.workout_row, NotesCursor, from, to);
        setListAdapter(notes);
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        super.onCreateOptionsMenu(menu);
        menu.add(0, INSERT_ID, 0, R.string.menu_insert);
        return true;
    

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) 
        switch(item.getItemId()) 
            case INSERT_ID:
                createNote();
                return true;
        

        return super.onMenuItemSelected(featureId, item);
    

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) 
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add(0, DELETE_ID, 0, R.string.menu_delete);
    

    @Override
    public boolean onContextItemSelected(MenuItem item) 
        switch(item.getItemId()) 
            case DELETE_ID:
                AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
                mDbHelper.deleteNote(info.id);
                fillData();
                return true;
        
        return super.onContextItemSelected(item);
    

    private void createNote() 
        Intent i = new Intent(this, WorkoutEdit.class);
        startActivityForResult(i, ACTIVITY_CREATE);
    

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) 
        super.onListItemClick(l, v, position, id);

        Intent i = new Intent(this, WorkoutEdit.class);
        i.putExtra(StrongDbAdapter.KEY_ROWID, id);

        startActivityForResult(i, ACTIVITY_EDIT);
    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) 
        super.onActivityResult(requestCode, resultCode, intent);
        fillData();
    

这是我的一些 WorkoutEdit 课程似乎正在发生问题。

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.ViewFlipper;

public class WorkoutEdit extends Activity 

    public TextView mTitleText;
    //private EditText mBodyText;
    private Long mRowId;
    private StrongDbAdapter mDbHelper;
    private ViewFlipper viewFlipper;
    public TextView squats;
    public boolean workoutA;
    public String workoutState;
    //private double rowId = mRowId;
    public String squatLabel;
    public Button confirmButton;
    private Long prevId ;





    private void populateFields() 
        if (mRowId != null) 
            Cursor note = mDbHelper.fetchNote(mRowId);
            startManagingCursor(note);
            //mTitleText.setText(note.getString(
                    //note.getColumnIndexOrThrow(StrongDbAdapter.KEY_TITLE)));
            workoutState=(note.getString(
                    note.getColumnIndexOrThrow(StrongDbAdapter.KEY_TITLE)));
            squats.setText(note.getString(note.getColumnIndexOrThrow(StrongDbAdapter.SQUAT_LABEL)));
        
    



    @Override
    protected void onSaveInstanceState(Bundle outState) 
        super.onSaveInstanceState(outState);
        saveState();
        outState.putSerializable(StrongDbAdapter.KEY_ROWID, mRowId);
    

    @Override
    protected void onPause() 
        super.onPause();
        saveState();
    

    @Override
    protected void onResume() 
        super.onResume();
        populateFields();
    



    //Saves all the data to the database
    private void saveState() 
        String title = workoutState;
        String squatLabel = squats.getText().toString();


        if (mRowId == null) 
            long id = mDbHelper.createNote(title, squatLabel);
            if (id > 0) 
                mRowId = id;
            
         else 
            mDbHelper.updateNote(mRowId, title);
        
           

    
    @Override
    protected void onDestroy() 
        super.onDestroy();
        if (mDbHelper != null) 
            mDbHelper.close();
        

    




这是我的 DbAdapter

*更新了创建语句*

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;


public class StrongDbAdapter 

    public static final String KEY_TITLE = "title";
    public static final String KEY_BODY = "body";
    public static final String KEY_ROWID = "_id";


    public static final String WORKOUT_STATE = "workoutState";

    public static final String SQUAT_LABEL = "squatLabel";

    private static final String TAG = "StrongDbAdapter";
    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;


    private static final String DATABASE_NAME = "data";
    private static final String DATABASE_TABLE = "notes";
    private static final int DATABASE_VERSION = 2;



    /**
     * Database creation sql statement
     */
    private static final String DATABASE_CREATE =
        "create table notes (_id integer primary key autoincrement , "
        + "title text," +
        " squatLabel text, workoutState text );";


    private final Context mCtx;

    private static class DatabaseHelper extends SQLiteOpenHelper 

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

        @Override
        public void onCreate(SQLiteDatabase db) 

            db.execSQL(DATABASE_CREATE);
        

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS notes");
            onCreate(db);
        
    

    /**
     * Constructor - takes the context to allow the database to be
     * opened/created
     * 
     * @param ctx the Context within which to work
     */
    public StrongDbAdapter(Context ctx) 
        this.mCtx = ctx;
    

    /**
     * Open the notes database. If it cannot be opened, try to create a new
     * instance of the database. If it cannot be created, throw an exception to
     * signal the failure
     * 
     * @return this (self reference, allowing this to be chained in an
     *         initialization call)
     * @throws SQLException if the database could be neither opened or created
     */
    public StrongDbAdapter open() throws SQLException 
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    

    public void close() 
        mDbHelper.close();
    



    public long createNote(String title, String squatLabel) 


        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_TITLE, title);
        //initialValues.put(WORKOUT_STATE, workoutState);
        initialValues.put(SQUAT_LABEL, squatLabel);

        return mDb.insert(DATABASE_TABLE, null, initialValues);
    

    /**
     * Delete the note with the given rowId
     * 
     * @param rowId id of note to delete
     * @return true if deleted, false otherwise
     */
    public boolean deleteNote(long rowId) 

        return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
    

    /**
     * Return a Cursor over the list of all notes in the database
     * 
     * @return Cursor over all notes
     */
    public Cursor fetchAllNotes() 

        return mDb.query(DATABASE_TABLE, new String[] KEY_ROWID, KEY_TITLE,
                WORKOUT_STATE, null, null, null, null, null);
    

    /**
     * Return a Cursor positioned at the note that matches the given rowId
     * 
     * @param rowId id of note to retrieve
     * @return Cursor positioned to matching note, if found
     * @throws SQLException if note could not be found/retrieved
     */
    public Cursor fetchNote(long rowId) throws SQLException 

        Cursor mCursor =

            mDb.query(true, DATABASE_TABLE, new String[] KEY_ROWID,
                    KEY_TITLE, WORKOUT_STATE, KEY_ROWID + "='" + rowId+"'", null,
                    null, null, null, null);
        if (mCursor != null) 
            mCursor.moveToFirst();
        
        return mCursor;

    

    /**
     * Update the note using the details provided. The note to be updated is
     * specified using the rowId, and it is altered to use the title and body
     * values passed in
     * @return true if the note was successfully updated, false otherwise
     */
    public boolean updateNote(long rowId, String title) 
        ContentValues args = new ContentValues();
        args.put(KEY_TITLE, title);
        //args.put(WORKOUT_STATE, workoutState);

        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
    

最后是我的 LogCat:

*使用新的 create 语句,这次没有这样的列 squatLabel。*

08-05 18:57:05.336: E/AndroidRuntime(1131): FATAL EXCEPTION: main
08-05 18:57:05.336: E/AndroidRuntime(1131): java.lang.RuntimeException: Unable to start activity ComponentInfocom.anapoleon.android.stronglifts/com.anapoleon.android.stronglifts.WorkoutEdit: java.lang.IllegalArgumentException: column 'squatLabel' does not exist
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.ActivityThread.access$600(ActivityThread.java:122)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.os.Looper.loop(Looper.java:137)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.ActivityThread.main(ActivityThread.java:4340)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at java.lang.reflect.Method.invokeNative(Native Method)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at java.lang.reflect.Method.invoke(Method.java:511)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at dalvik.system.NativeStart.main(Native Method)
08-05 18:57:05.336: E/AndroidRuntime(1131): Caused by: java.lang.IllegalArgumentException: column 'squatLabel' does not exist
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:301)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at com.anapoleon.android.stronglifts.WorkoutEdit.populateFields(WorkoutEdit.java:199)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at com.anapoleon.android.stronglifts.WorkoutEdit.onCreate(WorkoutEdit.java:82)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.Activity.performCreate(Activity.java:4465)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
08-05 18:57:05.336: E/AndroidRuntime(1131):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
08-05 18:57:05.336: E/AndroidRuntime(1131):     ... 11 more

提前致谢! :)

【问题讨论】:

修改“create”字符串后,您需要做两件事之一。增加 DATABASE_VERSION 以强制调用 onUpgrade(...) 或转到管理应用程序和清除数据以删除当前数据库以强制再次调用 onCreate(...) 非常感谢您的工作!但是我遇到了更多错误,但至少是一个开始。 请看我更新的答案。看起来您没有将 SQUAT_LABEL 字段添加到 db.query() 方法的参数中。 【参考方案1】:

正如其他人所说,您的数据库中没有定义该列。

他们忽略告诉您的是,您将列添加到应用程序中的数据库架构之后,您必须执行以下两项操作之一。

1) 删除并重新安装您的应用,以便在创建数据库时使用数据库的新架构

2) 增加数据库的版本,以便调用 onUpgrade 方法并将数据库更新到新架构

【讨论】:

Crud,刚刚意识到 Squonk 一小时前在 cmets 中指出了这一点。好吧,由于没有人将其添加到他们的答案中,因此我将把它留在这里,直到有人这样做。 (我讨厌必须进入 cmets 才能找到完整/完整的答案)。 谢谢!我修复了我的第一列错误,但现在我又得到了它,但没有这样的列:squatLabel,即使它在我的创建语句中并且我已经清除了数据库数据/重新安装了我的应用程序很多次。【参考方案2】:

您更新后的 Create DB 语句似乎是正确的。

关于下一个错误:它表明您永远不会关闭数据库和游标。 使用 DB 时,我通常使用下一个模板:

openReadableDatabase(); // or openWritableDatabase();

// do some work with DB

closeDatabase();

上述方法可能如下所示:

private void closeDatabase() 
    if (_db != null && _db.isOpen()) 
        _db.close();
    


private void openReadableDatabase() 
    _db = getReadableDatabase();


private void openWritableDatabase() 
    _db = getWritableDatabase();

同样可以应用于游标对象:

Cursor cursor = _db.query(TABLE_NAME, FROM, null, null, null, null, null);

// do some work with cursor

cursor.close();

FROM 是一个列名数组。注意:最后一列名称后面的逗号不是拼写错误。

private static final String[] FROM =  COLUMN1_NAME, COLUMN2_NAME, ;

更新: 您应该在 db.query() 方法中的数据检索参数中添加一个 SquatLabel 列(对于 fetchNote 方法也是如此):

public Cursor fetchAllNotes() 
    return mDb.query(DATABASE_TABLE, new String[] KEY_ROWID, KEY_TITLE,
        SQUAT_LABEL, WORKOUT_STATE, null, null, null, null, null);

【讨论】:

谢谢!我添加了一个关闭 DbHelper 并消除错误的方法。现在我只是被这个 java.lang.IllegalArgumentException: column 'squatLabel' does not exist 查看更新后的答案。您应该在 db.query() 方法中的 columns 参数中添加一个蹲标签列。【参考方案3】:

查看您的创建语句:

private static final String DATABASE_CREATE =
        "create table notes (_id integer primary key autoincrement , "
        + "title text," +
        " squatLabel text );";

您没有包含workoutState。只需将该列添加到 create 语句中即可。

【讨论】:

@user1576752 我很难相信它会给出完全相同的错误。您还应该使用正确的 create 语句更新您的问题。您还应该使用正确的语句再次运行它,看看它是否真的给您完全相同的错误。 我更新了语句和日志,如果不是相同的错误消息,它看起来很相似 @Recursed :请参阅我对 OP 问题的评论。除非删除原始数据库或增加版本号以强制升级,否则仅修改 create 语句不会解决问题。这是 Android SQLiteOpenHelper 类如何工作的一个怪癖。当然,您的答案实际上是正确的 - 它只需要一个额外的步骤。【参考方案4】:

如果有人仍然面临同样的错误,如果您正在查询字符串,请确保添加引号。

例如,我这样写时出错了:

        Cursor cursor = this.database.query(
            SQLiteHelper.TABLE_NAME,
            new String[]ID, FNAME,
            "fname"+" = "+name,   ......

我解决了这个问题:

        Cursor cursor = this.database.query(
            SQLiteHelper.TABLE_NAME,
            new String[]ID, FNAME,
            "fname"+" = "+"'"+name+"'", .....

【讨论】:

以上是关于Android sqlite 数据库报错 SQLiteException no such column的主要内容,如果未能解决你的问题,请参考以下文章

Android 数据存储 - 文件与 SQLite

如何将数据从 postgres 数据库导入到 android sqlite

Android-SQLite数据库实例

sqlite中的replaceinsertupdate之前的区别

Android 数据库管理— — —升级数据库

Android sqlite 数据库报错 SQLiteException no such column