Java SQLite插入约束字段时出错-为什么?
我不熟悉android编程和使用SQLite。我试图插入一个名为“menu”的数据库,该数据库有一个名为“items”的表。此表的属性为“名称”和“价格”,分别为文本和实数。(我想为所有代码道歉,但我认为这些代码会很有用)。我的“MySQLiteHelper”类创建如下表: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
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.
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.