Sorry I had to remove my earlier post because of work . . here is a more generic fix to the problem I was having that does not reference anything in particular but works more like a skeleton of how it should be done using a solution i was given.
///--------------------Most Recent Edits to this Post----------------------------------
Okay guys and gals, turns out there is no error in my syntax here however my methodology was not the smartest. I was filled in on how to do this correctly for those of you on here who need a solution here it is for creating multiple tables in a single database with android (at least the way I did it.) .......
Okay so clear all the dbHelper classes imbedded in your dbAdapters and create a stand alone dbhelper class that extends SQLiteOpenHelper. By doing this you can use your classes to access the information while referencing the SliteOpenHelper stand alone dbAdapter. Here is an example of the Stand alone helper class and one of my adapters i used to access it.
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DatabaseHelper extends SQLiteOpenHelper
{
//-----------------------------------Member Variables---------------------------
private static final String DATABASE_NAME = "databaseName";
private static final int DATABASE_VERSION = 1;
//----------------------------------------------------------------------
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// nothing here cause not upgrading version right now
Log.w(DatabaseHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_NAME + Table1DbAdapter.DATABASE_TABLE);
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_NAME + Table2DbAdapter.DATABASE_TABLE);
onCreate(db);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(Table1DbAdapter.CREATE_TABLE_ONE);
db.execSQL(Table2DbAdapter.CREATE_TABLE_TWO);
}
}
// and one example of how to use this helper from a class that accesses table1 (done the same way for all other tables)
public class Table1DbAdapter {
static final String DATABASE_TABLE = "table1";
public static final String KEY_TITLE = "title";
public static final String KEY_BODY = "body";
public static final String KEY_ROWID = "_id";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
static final String CREATE_TABLE_ONE =
"create table " + DATABASE_TABLE + "("
+ KEY_ROWID + " integer primary key autoincrement, "
+ KEY_TITLE + " text not null, "
+ KEY_BODY + " text not null )";
private final Context mCtx;
public Table1DbAdapter(Context ctx) {
this.mCtx = ctx;
}
// create the database
public Table1DbAdapter open() throws android.database.SQLException{
this.mDbHelper = new DatabaseHelper(mCtx);
this.mDb = mDbHelper.getWritableDatabase();
return this;
}
// create an entry
public long createEntry(String title, String body){
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_TITLE, title);
initialValues.put(KEY_BODY, body);
return
this.mDb.insert(DATABASE_TABLE, null, initialValues);
}
// delete an Entry
public boolean deleteEntry(long rowId){
return
this.mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" +rowId, null) > 0;
}
// fetch all Entries
public Cursor fetchAllEntries(){
return this.mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
KEY_BODY}, null, null, null, null, null);
}
// fetch an Entry
public Cursor fetchEntry(long rowId) throws SQLException{
Cursor mCursor =
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
KEY_BODY}, KEY_ROWID +"="+
rowId, null, null, null, null, null);
if (mCursor != null){
mCursor.moveToFirst();
}
return mCursor;
}
// update an Entry
public boolean updateEntry(long rowId, String title, String body){
ContentValues args = new ContentValues();
args.put(KEY_TITLE, title);
args.put(KEY_BODY, body);
return
this.mDb.update(DATABASE_TABLE, args, KEY_ROWID + "="+ rowId, null)> 0;
}
// close the database
public void close(){
mDbHelper.close();
}
}
// I hope this helps.... sorry again for the deletion earlier but this is how it should be done. . . at least until I find something more efficient
OK, no offence but your methodology really needs some work. That code is a complete tangle.
As to explaining the reason for the exception...
At no point in that code does an instance of MainDbAdapter ever get created. The result is, its onCreate(...) method is never called so basically you don't have any tables (all of them, I mean, not just the amenities table will be missing).
To be honest I wouldn't nest a derived SQLiteOpenHelper into an 'adapter' of any sort.
Create a stand-alone class which extends SQLiteOpenHelper and just create an instance of it whenever you need it.
Get rid of the nested DatabaseHelper classes in your 'adapter' classes, re-build, look at what eclipse complains about (assuming you're using eclipse) and then patch it up by pointing everything at your stand-alone SQLiteOpenHelper.
It looks like your database exists, but your table (amenities) does not.
Therefore onCreate() is never called because the DB exists already.
When the SELECT query is subsequently run, it throws the exception.
I'm pretty sure that if you use a debugger and step through your code, you'll see this happening.
Solution:
Delete the DB from your device OR
Execute your CREATE TABLE statement directly from sqlite3
The best source to get to know SQLite syntax is SQLite Homepage
And your syntax looks correct.
EDIT: Yep, you'll need to delete database from app folder and let application create a new database for you like someone in the comment suggested you to do. Because onCreate() method checks if database exists or not and if not then creates a new one.
You can delete database by going fo DDMS in Eclipse. The databases are usually stored in
/data/data/your.applications.package/databases
Related
I want to get a primary key of a saved object in a table in database I wrote a class to handle my database I want to add a function to it for getting the Id (I tried to give id to objects manually it didn't go well so I prefer the primary key id)so how should this function look like?and also if u see a thing that needs changing in my code please let me know.
public class DataBaseHandler extends SQLiteOpenHelper {
private static int _ID =0;
private int ID =0;
private ArrayList<marker_model> markerList=new ArrayList<>();
public DataBaseHandler(Context context) {
super(context, Constans.TABLE_NAME, null, Constans.DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+Constans.TABLE_NAME+
" ("+Constans.MARKER_ID+" INTEGER PRIMARY KEY, "+
Constans.MARKER_TITLE+" TEXT, " +Constans.MARKER_DESCRIPTION+" TEXT ,"+Constans.My_MARKER_ID+" INT );");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+Constans.TABLE_NAME);
onCreate(db);
}
public void AddMarker(marker_model marker){
marker.set_Id(_ID);
SQLiteDatabase db=this.getWritableDatabase();
ContentValues values=new ContentValues();
values.put(Constans.MARKER_TITLE,marker.getTitle());
values.put(Constans.My_MARKER_ID,marker.get_Id());
values.put(Constans.MARKER_DESCRIPTION,marker.getDescription());
db.insert(Constans.TABLE_NAME,null,values);
db.close();
Log.d(TAG, "AddMarker: Successfully added to DB");
_ID++;
}
public ArrayList<marker_model> getMarkers(){
markerList.clear();
SQLiteDatabase db =getReadableDatabase();
Cursor cursor=db.query(Constans.TABLE_NAME
,new String[]{Constans.My_MARKER_ID,Constans.MARKER_TITLE,
Constans.MARKER_DESCRIPTION},null,null,null,null,null);
if (cursor.moveToFirst()){
do {
ID=0;
marker_model model=new marker_model();
model.set_Id(_ID);
model.setDescription(cursor.getString(cursor.getColumnIndex(Constans.MARKER_DESCRIPTION)));
model.setTitle(cursor.getString(cursor.getColumnIndex(Constans.MARKER_TITLE)));
markerList.add(model);
ID++;
}while(cursor.moveToNext());
}
cursor.close();
db.close();
return markerList;
}
public int getMarkerPrimaryId(Marker marker){
}
}
Assuming that you want to get the _id (the primary key) from the database and that marker is an instance of a marker_model object AND that
marker_model has methods getTitle and getDescription that return a string with the respective values, then something along the lines of the following would work.
public long getMarkerPrimaryId(Marker marker){
long rv = 0;
SQLiteDatabase db = getReadableDatabase();
String[] columns = new String[]{Constans.My_MARKER_ID};
String whereclause = Constans.MARKER_TITLE + "=?" +
Constans.MARKER_DESCRIPTION + "=?";
String[] whereargs = new String[]{
marker.getTitile,
marker.getDescription
}
Cursor cursor = db.query(Constans.TABLE_NAME,
columns,
whereclause,
whereargs,
null,null,null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
rv = cursor.getLong(cursor.getColumnIndex(Constans.My_MARKER_ID);
}
cursor.close;
db.close;
return rv;
}
However, if your issue is that getMarkers is not setting the Id member appropriately (i.e. to match the id in the database), then changing model.set_Id(_ID);
to
model.set_Id(cursor.getLong(cursor.getColumnIndex(Constans.My_MARKER_ID));
would suffice.
If your expectation is that an automatically generated incrementing _id is to be used the addMarker is a little flawed. Simply by removing the line values.put(Constans.My_MARKER_ID,marker.get_Id()); will result in _id being automatically generated (which how _id's tend to be used).
The following (BACKGROUND paragraph mostly) explains much about automatically generated unique identifiers (even though it is about AUTOINCREMENT you likely DO NOT want to code AUTOINCREMENT).
Id suggest that rather than :-
if (cursor.moveToFirst()){
do {
...
}while(cursor.moveToNext());
using :-
while (cursor.moveToNext() {
....
}
is simpler (a cursor, when created, will be positioned to before the first row (moveToPosition(-1) has the same effect) , moveToNext() will move to the first row the first time, if there are no rows the loop will not be entered (you may wish to consider this and the state of returned markerlist)).
Note! the above has been written without testing, so there may be the odd mistake.
I am a bit new to SQLite so please bear with me. I am creating a table and trying to access data from it but somehow I am getting this error.
android.database.sqlite.SQLiteException: no such table: table_image (code 1): , while compiling: SELECT image_data FROM table_image WHERE image_name= ' a '
Things that I did after the error came:
1.) Uninstalled the app and installed it again.
2.) Checked for spaces in the table creation code. It looks right to me.
I am not sure why this error is appearing then. Can someone please help me.
Thanks !!
My DatabaseHelper class
public class DatabaseHelper extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "database_name";
// Table Names
public static final String DB_TABLE = "table_image";
// column names
public static final String KEY_NAME = "image_name";
public static final String KEY_IMAGE = "image_data";
// Table create statement
private static final String CREATE_TABLE_IMAGE = "CREATE TABLE " + DB_TABLE + " ("+
KEY_NAME + " TEXT, " +
KEY_IMAGE + " BLOB"+")";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// creating table
db.execSQL(CREATE_TABLE_IMAGE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// on upgrade drop older tables
db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
// create new table
onCreate(db);
}
}
Adding stuff to db in another class
// Calling addEntry
addEntry(name, img);
// Function to add entry
public void addEntry( String name, byte[] image) throws SQLiteException {
ContentValues cv = new ContentValues();
cv.put(DatabaseHelper.KEY_NAME, name);
cv.put(DatabaseHelper.KEY_IMAGE, image);
database.insert(DatabaseHelper.DB_TABLE, null, cv);
}
Then I am tying to get data from it.
SQLiteDatabase db = openOrCreateDatabase(DatabaseHelper.DB_TABLE, MODE_PRIVATE, null);
String selectQuery = "SELECT image_data FROM "+DatabaseHelper.DB_TABLE+" WHERE image_name= ' "+"a"+" ' ";
Cursor cursor = db.rawQuery(selectQuery,null);
byte[] image = cursor.getBlob(1);
openOrCreateDatabase() is not using SQLiteOpenHelper where you have the table creation code.
To get a SQLiteDatabase managed by SQLiteOpenHelper, call e.g. getWritableDatabase() on your helper object.
After fixing that, uninstall the app once more to get rid of the empty database created by openOrCreateDatabase().
Have you tried uninstalling your app and running it again?
error says "no such table: table_image", this situation can occur if you test your app with a DB with lesser number of tables and introduce a table later on.
once you relaunch your app with an additional table an older version of DB is already present and onCreate of your DBHelper will not be called and the new table will not be added in your db.
uninstalling the app will clear any previous instance of DB and onCreate will be called again and you will start with a fresh tables.
I made two classes, the main class that extends Activity and the Database class that holds the database and it's methods. parts of the code from the database class are shown below.
the SQLiteOpenHelper class is a nested class inside the database class. I took it from an example I found on the internet. inside of this nested class is the method,
db.execSQL(SCRIPT_CREATE_DATABASE);
how do I create a new database? If I instantiate the Database class from the Main class like this:
Database db = new Database(this);
does that instantiation automatically instantiate the nested SQLiteOpenHelper class too? so i don't have to explicitly do that.
however for this example of how to create a database, i am confused. if every time I instantiate a new instance calling the addNewRow() method like this:
public void addNewRow(String label, int price){
Database db = new Database(context);
db.openToWrite();
db.insertNewRow(checkBoxStatus, label, price);
db.close();
}
then a new database is created on the "new Database(context)" call, and next I add the info to enter into the columns. and finally call db.close(), however every time i call the addNewRow method shown above, it will instantiate a new database and that also instantiates SQLiteOpenhelper class so a new database is created. that means the last database has been overwritten, and my last row added has been lost, is this correct?
how do i use this Database class to create a Database only once and then read and write things from it with multiple calls like this?
Database db = new Database(context);
db.openToWrite(); or db.openToRead();
// read or update or create new row in database
db.close();
the database class:
public class Database {
public static final String MYDATABASE_NAME = "my_database";
public static final String MYDATABASE_TABLE = "my_table";
public static final int MYDATABASE_VERSION = 1;
public static final String KEY_CHECKBOX_STATUS = "check_box_status";
public static final String KEY_CHECKBOX_LABEL = "check_box_label";
public static final String KEY_PRICE = "price";
//create table MY_DATABASE (ID integer primary key, Content text not null);
private static final String SCRIPT_CREATE_DATABASE =
"CREATE TABLE " + MYDATABASE_TABLE + " (" + "ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
"KEY_CHECKBOX_STATUS INTEGER, " + "KEY_CHECKBOX_LABEL TEXT, " + " KEY_PRICE INTEGER" + ");";
SQLiteDatabase sqLiteDatabase;
SQLiteHelper sqLiteHelper;
Context context;
public Database(Context c){
context = c;
}
// after this all the rest of the methods for get and set of database values
code for the SQLiteOpenHelper class, nested inside of the Database Class:
public class SQLiteHelper extends SQLiteOpenHelper {
public SQLiteHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(SCRIPT_CREATE_DATABASE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
Yes, every time you instantiate a Database class a SQLiteHelper is instantiate. But the SQLiteHelper onCreate is only called if the database does not exist. You can test this by adding a new column to one of the table and then try to insert a row having value in this column then your app will crash. The error would be "no such column". You then need to clear your data or change the version of your database or uninstall your app to have your change table to be recreated.
Whenever you want to just open your database, you need to use this:
myDatabase = myOpenHelper.getWritableDatabase();
This won't create a new database. It would just return the instance of existing database on which you can do Read/Write operations.
Refer this to get a firm idea of how creating database works in Sqlite. Hope it helps.
private static final String SCRIPT_CREATE_DATABASE =
"CREATE TABLE IF NOT EXISTS " + MYDATABASE_TABLE + " (" + "ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
"KEY_CHECKBOX_STATUS INTEGER, " + "KEY_CHECKBOX_LABEL TEXT, " + " KEY_PRICE INTEGER" + ");";
Use this query while creating the table. It will create the Table if it doesn't exist.
I try to drop table programmatically nothing error show in logcat, but there has no any result :
Here my Database Helper class :
public class database1 extends SQLiteOpenHelper
{
private static final String DB_Name="database";
private static final int DB_Version=1;
private static final String tbl_arrival1="arrival1";
private static final String STRING_CREATE1 = "CREATE TABLE IF NOT EXISTS "+tbl_arrival1
+" (_f_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+"f_date TEXT,"
+"o_rder NUMERIC,"
+"rem_com TEXT);";
public database1 (Context ctx)
{
super(ctx,DB_Name,null,DB_Version);
}
#Override
public void onCreate(SQLiteDatabase database) {
databaseQuery.onCreate(database);
}
public static class databaseQuery
{
public static void onCreate(SQLiteDatabase database)
{
database.execSQL("DROP TABLE IF EXISTS "+tbl_arrival1);
database.execSQL(STRING_CREATE1);
}
}
}
I use this database helper in content provider :
database1 DBHelper ;
public Uri insert(Uri uri, ContentValues values)
{
long row_id;
SQLiteDatabase sqlDB = DBHelper.getWritableDatabase();
row_id=sqlDB.insert(tbl_arrival1, null, values);
if(row_id>0)
{
Uri _uri = ContentUris.withAppendedId(CONTENT_URI, row_id);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLException("Failed to insert into "+uri);
}
The problem is that, the query drop table, is not working!
All suggestion and answer would be highly appreciated...
thanks
I know I'm bit late but this question was relevant for me. In my case I tried to drop many tables in single a query, i. e.
drop table if exists table_name1;
drop table if exists table_name2;
drop table if exists table_name3;
so android's implementation of execSQL() executes only single sql statement
onCreate will work only once at time of creation once the database is created you should make use of onUpgrade() to drop table if any changes has been made to old version
EDIT
http://www.vogella.com/articles/AndroidSQLite/article.html
Your code seems to be fine. You are calling DROP TABLE and then creating again subsequently. How you checked the DROP TABLE is not working?
I've been racking my brain on this for days and I just can't wrap my head around using SQLite databases in Android/Java. I'm trying to select two rows from a SQLite database into a ListArray (or two, one for each row. Not sure if that would be better or worse) and I just don't understand how to do it. I've tried various database manager classes that I've found but none of them do what I need and it seems that I should be able to do this simple task without the extra features I've seen in other database managers. Is there any simple way to JUST query some data from an existing SQLite database and get it into a ListArray so that I can work with it? I realize I need to copy the database from assets into the Android database path and I can handle that part. I also need to be able to modify one of the columns per row. I don't need to create databases or tables or rows. I implore someone to help me with this as I consider any code I've written (copied from the internet) to be completely useless.
You can create a method like this :
private List<MyItem> getAllItems()
List<MyItem> itemsList = new ArrayList<MyItem>();
Cursor cursor = null;
try {
//get all rows
cursor = mDatabase.query(MY_TABLE, null, null, null, null,
null, null);
if (cursor.moveToFirst()) {
do {
MyItem c = new MyItem();
c.setId(cursor.getInt(ID_COLUMN));
c.setName(cursor.getString(NAME_COLUMN));
itemsList.add(c);
} while (cursor.moveToNext());
}
} catch (SQLiteException e) {
e.printStackTrace();
} finally {
cursor.close();
}
return itemsList;
}
This will be inside your class let say MyDatabaseHelper where you will also have to declare a :
private static class DatabaseHelper extends SQLiteOpenHelper{
private final static String DATABASE_CREATE="create table " + MY_TABLE + " (id integer primary key, country string);";
public DatabaseHelper(Context context,String name, CursorFactory factory, int version){
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 "+ MY_TABLE);
onCreate(db);
}
}
used to open() and close() the database.