我正在尝试为我的Android应用程序创建一个多表数据库。我正在遵循本网站http://androidforbeginners.blogspot.com/2010/01/creating-multiple-sqlite-database.html提出的建议。我继续得到以下错误。该错误似乎是由数据库表的onCreate引起的。
如果你在DBHelper类中查看我的onCreate,我有两个注释掉了。这使得它无论哪一个都不公开都可以工作。
必须有一种创建多表数据库的方法,因为数据库中的单个表几乎违背了拥有数据库的目的。
10-23 02:11:35.383: ERROR/AndroidRuntime(300): Caused by: android.database.sqlite.SQLiteException: Can't upgrade read-only database from version 0 to 1: /data/data/com.parkingticket/databases/Tickets.db
提前致谢。
这是我的代码
package com.parkingticket;
import java.sql.SQLException;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class TicketDBAdapter
{
private static final String DATABASE_NAME="Tickets.db";
private static final int DATABASE_VERSION = 1;
private static final String PARKEDCARS_TABLE = "ParkedCars";
private static final String PARKINGMETERS_TABLE = "ParkingMeters";
private static final String PARKINGTICKETS_TABLE = "ParkingTickets";
private static final String POLICEOFFICERS_TABLE = "PoliceOfficers";
// The name and column index for each column in PARKEDCARS
public static final String KEY_CARID = "carID";
public static final int CARID_COLUMN = 0;
public static final String KEY_CARMAKE = "Make";
public static final int CARMAKE_COLUMN = 1;
public static final String KEY_CARMODEL = "Model";
public static final int CARMODEL_COLUMN = 2;
public static final String KEY_CARCOLOR = "Color";
public static final int CARCOLOR_COLUMN = 3;
public static final String KEY_CARLICENSENUMBER = "LicenseNumber";
public static final int CARLICENSENUMBER_COLUMN = 4;
public static final String KEY_CARMINUTESPARKED = "MinutesParked";
public static final int CARMINUTESPARKED_COLUMN = 5;
// The name and column index for each column in PARKINGMETERS
public static final String KEY_METERID = "meterID";
public static final int METERID_COLUMN = 0;
public static final String KEY_MINUTESPURCHASED = "MinutesPurchased";
public static final int MINUTESPURCHASED_COLUMN = 1;
// The name and column index for each column in PARKINGTICKETS
//TODO create the columns and indexs for parking tickets
// The name and column index for each column in POLICEOFFICERS
public static final String KEY_OFFICERID = "officerID";
public static final int OFFICERID_COLUMN = 0;
public static final String KEY_OFFICERNAME = "Name";
public static final int OFFICERNAME_COLUMN = 1;
public static final String KEY_OFFICERBADGE = "BadgeNumber";
public static final int OFFICERBADE_COLUMN = 2;
//Variable to hold the database instance
private SQLiteDatabase ticketDB;
//Context of the application using the database.
private final Context context;
//Database open/upgrade helper
private TicketDBHelper ticketDBHelper;
public TicketDBAdapter(Context _context)
{
context = _context;
ticketDBHelper = new TicketDBHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void open() throws SQLiteException
{
try
{
ticketDB = ticketDBHelper.getWritableDatabase();
}
catch(SQLiteException ex)
{
ticketDB = ticketDBHelper.getReadableDatabase();
}
}
public void close()
{
ticketDB.close();
}
//Insert a new ParkedCar
public long insertParkedCar(ParkedCar _car)
{
//Create a new row of values to insert
ContentValues newParkedCarValues = new ContentValues();
//Assign values for each row
newParkedCarValues.put(KEY_CARMAKE, _car.getMake());
newParkedCarValues.put(KEY_CARMODEL, _car.getModel());
newParkedCarValues.put(KEY_CARCOLOR, _car.getColor());
newParkedCarValues.put(KEY_CARLICENSENUMBER, _car.getLicenseNumber());
newParkedCarValues.put(KEY_CARMINUTESPARKED, _car.getMinutesParked());
//Insert the row
return ticketDB.insert(PARKEDCARS_TABLE, null, newParkedCarValues);
}
//Remove a ParkedCar based on its index
public boolean removeParkedCar(long _rowIndex)
{
return ticketDB.delete(PARKEDCARS_TABLE, KEY_CARID + "=" + _rowIndex, null)>0;
}
//Update a ParkedCar's MinutesParked
//TODO Create an update for ParkedCar's minutesParked.
public Cursor getAllParkedCarsCursor()
{
return ticketDB.query(PARKEDCARS_TABLE, new String[] {KEY_CARID, KEY_CARMAKE, KEY_CARMODEL, KEY_CARCOLOR, KEY_CARLICENSENUMBER, KEY_CARMINUTESPARKED}, null, null, null, null, null);
}
public Cursor setCursorParkedCar(long _rowIndex) throws SQLException
{
Cursor result = ticketDB.query(true, PARKEDCARS_TABLE, new String []{KEY_CARID}, KEY_CARID + "=" + _rowIndex, null, null, null, null, null);
if ((result.getCount() == 0) || !result.moveToFirst())
{
throw new SQLException("No ParkedCar found for row: " + _rowIndex);
}
return result;
}
public static class TicketDBHelper extends SQLiteOpenHelper
{
public TicketDBHelper(Context context, String name, CursorFactory factory, int version)
{
super(context, name, factory, version);
}
//SQL Statement to create PARKEDCARS table
private static final String PARKEDCARS_CREATE = "create table " + PARKEDCARS_TABLE + " (" + KEY_CARID + " integer primary key autoincrement, " + KEY_CARMAKE + " text not null," + KEY_CARMODEL + " text not null," + KEY_CARCOLOR + " text not null," + KEY_CARLICENSENUMBER + " text not null," + KEY_CARMINUTESPARKED + "int not null);";
//SQL Statement to create ParkingMeters table
private static final String PARKINGMETERS_CREATE = "create table" + PARKINGMETERS_TABLE + " (" + KEY_METERID + " integer primary key autoincrement, " + KEY_MINUTESPURCHASED + " int not null);";
//SQL Statement to create ParkingTickets table
//TODO create the statement for parkingTickets
//SQL Statement to create PoliceOfficers table
private static final String POLICEOFFICERS_CREATE = "create table" + POLICEOFFICERS_TABLE + " (" + KEY_OFFICERID + " integer primary key autoincrement, " + KEY_OFFICERNAME + " text not null," + KEY_OFFICERBADGE + "text not null);";
//Called when no database exists in disk and the helper class needs to create a new one.
@Override
public void onCreate(SQLiteDatabase _db)
{
//_db.execSQL(PARKEDCARS_CREATE);
_db.execSQL(PARKINGMETERS_CREATE);
//_db.execSQL(POLICEOFFICERS_CREATE);
}
//Called when there is a database verion mismatch meaning that the version of the database on disk needs to be upgraded to the current version
@Override
public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion)
{
//Log the version upgrade.
Log.w("TaskDBAdapter", "Upgrading from version " + _oldVersion + " to " + _newVersion + ", which will destroy all old data");
//Upgrade the existing database to conform to the new version
//Multiple previous versions can be handled by comparing _oldVersoin and _newVersion values
//The simplest case is to drop teh old table and create a new one.
_db.execSQL("DROP TABLE IF EXISTS " + PARKEDCARS_TABLE);
_db.execSQL("DROP TABLE IF EXISTS " + PARKINGMETERS_TABLE);
_db.execSQL("DROP TABLE IF EXISTS " + POLICEOFFICERS_TABLE);
onCreate(_db);
}
}
}
答案 0 :(得分:1)
我知道我迟到了,但我认为这可能有助于其他人阅读这篇文章。 我有同样的问题,它是关于空格的,当你在编写关于空间的SQL查询时要非常小心。例如在上面的代码中,你可以注意到最后没有空间:
KEY_OFFICERBADGE + "text not null"
基本上,你已经声明了一个没有类型的列。 希望它有所帮助。
答案 1 :(得分:0)
当您抓住Log
以查看open()
是否失败并随后调用SQLiteException
时,在ticketDBHelper.getWritableDatabase()
方法中添加ticketDBHelper.getReadableDatabase()
语句, name暗示,以只读方式打开数据库。
答案 2 :(得分:0)
我写了一个多表应用程序,工作正常。听起来你可能在打开现有的db文件进行写入时遇到问题。我建议从您的模拟器/设备中删除它,增加版本号并重新运行应用程序。我的开放方法粘贴在这里。
public DbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
Anthony Nolan
答案 3 :(得分:0)
我找到了问题的解决方案,但没有在此网站上直接回答。
http://pheide.com/page/11/tab/24#post13
为什么使用抽象类创建数据库扩展该类工作我无法弄清楚我的生活因为看起来我在上面的一个班级中做同样的事情。尽管如此,只要我玩过它就会起作用。