Java SQLite插入约束字段时出错-为什么?

Java SQLite插入约束字段时出错-为什么?,java,android,sqlite,Java,Android,Sqlite,我不熟悉android编程和使用SQLite。我试图插入一个名为“menu”的数据库,该数据库有一个名为“items”的表。此表的属性为“名称”和“价格”,分别为文本和实数。(我想为所有代码道歉,但我认为这些代码会很有用)。我的“MySQLiteHelper”类创建如下表: package com.example.sqlite; import android.content.Context; import android.database.sqlite.SQLiteDatabase; impo

我不熟悉android编程和使用SQLite。我试图插入一个名为“menu”的数据库,该数据库有一个名为“items”的表。此表的属性为“名称”和“价格”,分别为文本和实数。(我想为所有代码道歉,但我认为这些代码会很有用)。我的“MySQLiteHelper”类创建如下表:

package com.example.sqlite;

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

public class MySQLiteHelper extends SQLiteOpenHelper {

    //Creating the items table
    public  static final String TABLE_ITEMS = "items";
    public  static final String ITEMS_COLUMN_NAME = "name";
    public  static final String ITEMS_PRICE = "price";



    private static final String DATABASE_NAME  = "menu";
    private static final int DATABASE_VERSION  = 1;

    // create table comments(
    //   _id integer primary key autoincrement,
    //   comment text not null );
    private static final String TABLE_CREATE_ITEMS = "create table "
            + TABLE_ITEMS + "( " + ITEMS_COLUMN_NAME + " text primary key, "
            + ITEMS_PRICE + " real not null );";

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

    @Override
    public void onCreate( SQLiteDatabase database ) {
        //Create the items table
        database.execSQL( TABLE_CREATE_ITEMS );
        //Create the combos table
        //database.execSQL(TABLE_CREATE_COMBO);
    }

    @Override
    public void onUpgrade( SQLiteDatabase db, int oldVersion, int newVersion ) {
        Log.w( MySQLiteHelper.class.getName( ), "Upgrading database from version "
                + oldVersion + " to " + newVersion + ", which will destroy all old data" );
        db.execSQL( "DROP TABLE IF EXISTS" + TABLE_CREATE_ITEMS );
        //db.execSQL( "DROP TABLE IF EXISTS" + TABLE_CREATE_COMBO );
        onCreate( db );
    }
}
我可以确认数据库“菜单”是在data/data/package/databases文件夹中创建的。尽管我无法使用adb shell连接到SQLite,所以我无法确认表模式。单击“插入”按钮后,将调用my datasource.createComment(String,Float):

public void onClick (View v) {
    @SuppressWarnings("unchecked")
    //Load up the current values in the adapter into this adapter object
            ArrayAdapter<Comment> adapter = (ArrayAdapter<Comment>)getListAdapter();
    //Set comment to null
    Comment comment = null;
    //Check to see which button was pressed
    switch (v.getId()) {
        case R.id.insert:
            String[] option = new String[] {"One", "Two", "Three"};
            int index = new Random().nextInt(3);
            //When inserting comment you just have to pass value
            comment = datasource.createComment("TEST", (float) 12.30);
            adapter.add(comment); //Adding to listview
            break;
        case R.id.delete:
            if(getListAdapter().getCount() > 0) {
                comment = (Comment)getListAdapter().getItem(0);
                adapter.remove(comment);//removing from listview
                datasource.deleteComment(comment); //delete from db.
            }
            break;
    }
    //Updating the adapter
    adapter.notifyDataSetChanged();
}
下面是我的“CommentsDataSource”代码。请忽略createComment()之后的方法。我一次编辑一个方法

public class CommentsDataSource {

    // Database fields
    //Used toe xecute commands on db.
    private SQLiteDatabase database;
    //Opening up the mysqlhelper which is in charge of opening up connection and maintaining
    private MySQLiteHelper dbHelper;
    //Holds all the values from the database
    private String[] allColumnsItems = { MySQLiteHelper.ITEMS_COLUMN_NAME,
            MySQLiteHelper.ITEMS_PRICE };

    //Creating the default constructor
    public CommentsDataSource(Context context) {
        //Give context to the class that manages the connection
        dbHelper = new MySQLiteHelper(context);
    }

    //Opening up the connction to the db
    public void open() throws SQLException {
        //Open the db for reading and writing
        database = dbHelper.getWritableDatabase(); //getWritableDatabase is what opens the connection
    }

    //Closing the database
    public void close() throws SQLException {
        dbHelper.close();
    }

    //Creating and commiting comment
    public Comment createComment(String comment, float price) {
        //Insert into comments values('')
        ContentValues values = new ContentValues();
        //Load the column id and value into ContentValues
        values.put(MySQLiteHelper.ITEMS_COLUMN_NAME, comment);
        values.put("price", price);
        //Now insert into table
        long insertID = database.insert(MySQLiteHelper.TABLE_ITEMS, null, values);
        if(insertID == -1) {
            System.out.println("JSDLFJLSJDFL");
        }
        //Create a cursor to keep track of results. When creating cursors they equal database.query
        Cursor cursor =  database.query(MySQLiteHelper.TABLE_ITEMS, allColumnsItems, null, null, null, null, null);
        //Move cursor tot he front
        cursor.moveToFirst();
        //Return the comment which is added to listview
        return cursorToComment(cursor);
    }

    public void deleteComment(Comment comment) {
        // select id, comment from comments;
        long id = comment.getId();
        //Debug purposes
        System.out.println("Comment to be deleted: " + id);
        //Deleting from db
        database.delete(MySQLiteHelper.TABLE_ITEMS, MySQLiteHelper.ITEMS_COLUMN_NAME + "=" + comment, null);
    }

    public List<Comment> getAllComments() {
        //Select * from comments
        List<Comment> comments = new ArrayList<Comment>();
        //Fetching the results of query into cursor
        Cursor cursor = database.query(MySQLiteHelper.TABLE_ITEMS, allColumnsItems, null, null, null, null, null);
        //Move to front of cursor
        cursor.moveToFirst();
        //Iterate through cursor
        while(!cursor.isAfterLast()) {
            Comment comment = cursorToComment(cursor);
            //Add results to arraylist
            comments.add(comment);
            cursor.moveToNext();

        }
        cursor.close();
        return comments;
    }

    public Comment cursorToComment(Cursor cursor) {
        Comment comment = new Comment();
        comment.setId(cursor.getLong(0));
        comment.setComment(cursor.getString(1));
        return comment;
    }

}
公共类CommentsDataSource{
//数据库字段
//用于在数据库上执行命令。
专用数据库;
//打开mysqlhelper,它负责打开连接和维护
私有MySQLiteHelper-dbHelper;
//保存数据库中的所有值
私有字符串[]allColumnsItems={MySQLiteHelper.ITEMS\u COLUMN\u NAME,
MySQLiteHelper.ITEMS\u PRICE};
//创建默认构造函数
公共评论数据源(上下文){
//为管理连接的类提供上下文
dbHelper=新的MySQLiteHelper(上下文);
}
//打开与数据库的连接
public void open()引发SQLException{
//打开数据库进行读写操作
database=dbHelper.getWritableDatabase();//getWritableDatabase是打开连接的工具
}
//关闭数据库
public void close()引发SQLException{
dbHelper.close();
}
//创建和提交评论
public Comment createComment(字符串注释、浮动价格){
//插入注释值(“”)
ContentValues=新的ContentValues();
//将列id和值加载到ContentValues中
value.put(MySQLiteHelper.ITEMS\u COLUMN\u NAME,comment);
价值。卖出(“价格”,价格);
//现在插入到表中
long insertID=database.insert(MySQLiteHelper.TABLE_ITEMS,null,value);
if(insertID==-1){
System.out.println(“JSDLFJLSJDFL”);
}
//创建游标以跟踪结果。创建游标时,它们等于database.query
Cursor Cursor=database.query(MySQLiteHelper.TABLE_ITEMS,allColumnsItems,null,null,null,null);
//将光标移到前面
cursor.moveToFirst();
//返回添加到listview的注释
返回游标提示(游标);
}
公共无效删除注释(注释注释){
//选择id,从评论中选择评论;
long id=comment.getId();
//调试目的
System.out.println(“要删除的注释:+id”);
//从数据库中删除
database.delete(MySQLiteHelper.TABLE_ITEMS,MySQLiteHelper.ITEMS_COLUMN_NAME+“=”+注释,null);
}
公共列表getAllComments(){
//从注释中选择*
列表注释=新建ArrayList();
//将查询结果提取到游标中
Cursor Cursor=database.query(MySQLiteHelper.TABLE_ITEMS,allColumnsItems,null,null,null,null);
//移动到光标的前面
cursor.moveToFirst();
//遍历游标
而(!cursor.isAfterLast()){
注释注释=游标注释(游标);
//将结果添加到arraylist
注释。添加(注释);
cursor.moveToNext();
}
cursor.close();
返回评论;
}
公共注释游标注释(游标){
注释=新注释();
comment.setId(cursor.getLong(0));
comment.setComment(cursor.getString(1));
回复评论;
}
}
我努力想知道我的错误在哪里。我的约束都应该有效吗?

请尝试以下操作:

public void onClick (View v) {
@SuppressWarnings("unchecked")
    //Load up the current values in the adapter into this adapter object
            ArrayAdapter<Comment> adapter = (ArrayAdapter<Comment>)getListAdapter();
    //Set comment to null
    Comment comment = new Comment(); //have to change this from null to new Comment();
    //Check to see which button was pressed
    switch (v.getId()) {
        case R.id.insert:
            String[] option = new String[] {"One", "Two", "Three"};
            int index = new Random().nextInt(3);
            //When inserting comment you just have to pass value
            comment = datasource.createComment("TEST", (float) 12.30);
            adapter.add(comment); //Adding to listview
            break;
        case R.id.delete:
            if(getListAdapter().getCount() > 0) {
                comment = (Comment)getListAdapter().getItem(0);
                adapter.remove(comment);//removing from listview
                datasource.deleteComment(comment); //delete from db.
            }
            break;
    }
    //Updating the adapter
    adapter.notifyDataSetChanged();
}

在这里,您正在尝试使用文本主键创建表,理想情况下,该主键应该是自动递增的。这就是其返回约束失败的原因

 private static final String TABLE_CREATE_ITEMS = "create table "
        + TABLE_ITEMS + "( " + ITEMS_COLUMN_NAME + " text primary key, "
        + ITEMS_PRICE + " real not null );";
应该是

CREATE TABLE TableName(
_id     INTEGER PRIMARY KEY,      -- autoincrementing, for Android
NAME    TEXT,
[...]);
你可以参考

在查看代码之后,我可以假设您试图在表中使用唯一的项名称,对吗?如果是这样的话,那么这个错误是显而易见的。在表
items
中,您将
name
作为主键,每次都尝试插入
TEST
。表中已存在的

有三种方法可以解决这个问题

  • name
    列中删除主键约束。但是,之后可以输入重复的名称
  • 测试时不要硬编码值。生成唯一名称并将其插入。如下

    int index = new Random().nextInt(3);
    comment = datasource.createComment("TEST" + index, (float) 12.30);
    
    // concatenate `index` variable to `TEST` that's it.
    
  • 从用户(GUI)获取输入并将其插入表中


  • PS:方法
    nextInt(3)
    将返回从0到2的数字。测试代码时,会得到重复的名称。所以,在使用随机数生成器时要小心。我想推荐我的最后一点。

    我已经在createComment方法中使用了contentview。基本上我所做的就是打包这些值,然后运行SQliteDatabase命令,对吗?请尝试一下。根据。。还有一个空值,请删除您的
    onUpgrade()
    代码。如果您更改数据库版本,它将删除数据库(即使您的表中有数据),不幸的是,我得到了相同的错误。我也不确定如何在android studio上正确调试。尝试检查logcat并单击蓝色链接ahh是的,我确实忘记了_id,但我仍然收到相同的错误。添加索引似乎已经修复了它。我完全忽略了这个事实。非常感谢。这是一个简单的解决方案。正如其他答案中所建议的,请添加带有主键和自动递增的
    \u id
    CREATE TABLE TableName(
    _id     INTEGER PRIMARY KEY,      -- autoincrementing, for Android
    NAME    TEXT,
    [...]);
    
    int index = new Random().nextInt(3);
    comment = datasource.createComment("TEST" + index, (float) 12.30);
    
    // concatenate `index` variable to `TEST` that's it.