How do I handle multiple database tables cleanly in Android? - android

I'm trying to create an Android app that can handle a history of played games and their scores, but as I expand from the Notepad tutorial, this is turning into a rat's nest of repeated statements like this:
private static final String GAME_TABLE_CREATE =
"create table " + GAME_TABLE + " (_id integer primary key autoincrement, "
+ "title text not null);";
private static final String PLAY_TABLE_CREATE =
"create table " + PLAY_TABLE + " (_id integer primary key autoincrement, "
+ "game_id integer, game_date date);";
private static final String PLAYER_TABLE_CREATE =
"create table " + PLAYER_TABLE + " (_id integer primary key autoincrement, "
+ "name text not null);";
private static final String SCORE_TABLE_CREATE =
"create table " + SCORE_TABLE + " (_id integer primary key autoincrement, "
+ "game_id int, player_id int, score int);";
...
public void onCreate(SQLiteDatabase db) {
db.execSQL(GAME_TABLE_CREATE);
db.execSQL(PLAY_TABLE_CREATE);
db.execSQL(PLAYER_TABLE_CREATE);
db.execSQL(SCORE_TABLE_CREATE);
}
This seems like a nightmare for readability and maintainability. Any advice on how to better manage multiple SQL tables, and turn these kinds of lists into nice clean loops? I was thinking about trying to do it via resource string-arrays, but haven't been able to figure out how to manage that.

I haven't had to deal with this in the Android world but have in the past in the Web world. I'd said for starters you may want to look at an ORM for managing you statements. There seems to be some pointers here that might help.

I manage this by turning off formatting in Eclipse (you must be using Helios or higher) by using the statement //formatter: off (and turning it on after). This SO question will give you more information on that.
I also place all my initial SQL statements (CREATE, Triggers, etc.) inside a static String array. This way all your statements can be run with this code in your onCreate:
public static final String[] SQL_CREATE_TABLES = new String[] { TABLE_1, TABLE_2};
#Override
public void onCreate(SQLiteDatabase db) {
for (String sql : SQL_CREATE_TABLES)
db.execSQL(sql);
}
The SQL statements could also be placed in the strings.xml resource file, but I don't think that would help maintain readability or maintainability.

I ran into this same issue when first starting out, managing the create tables as statements inside the Android app became really cumbersome, especially trying to update the schemas as development progressed. What worked really well for me was simply placing a copy of my database in the assets folder and then copy the database to the data folder. The first time your DBAdapter starts you can check if the database already exists, if it doesn't you can then copy your database over. This is also handy where tables need to be prepopulated with data, or pre loaded with data for testing. It made life so much easier to manage the database schemas in a normal/GUI based database tool.
There are lots of Android copy database code examples, a simple Google search should set you in the right direction.
Hope this helps,
Cheers,

Related

Error while inserting data into Database using content values

I am trying to insert data in database but it is giving me following error.
table places has no column named PLACE_NAME (code 1): , while compiling: INSERT INTO places(PLACE_NAME,IS_SELECTED,placeID,LONGITUDE,LATITUDE) VALUES (?,?,?,?,?)
here is how I am creating my Database Table
// Create a table to hold the places data
final String SQL_CREATE_PLACES_TABLE = "CREATE TABLE IF NOT EXISTS " + PlaceContract.PlaceEntry.TABLE_NAME + " (" +
PlaceContract.PlaceEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + PlaceContract.PlaceEntry.COLUMN_PLACE_NAME + " VARCHAR, " +
PlaceContract.PlaceEntry.COLUMN_PLACE_LATITUDE + " VARCHAR, " + PlaceContract.PlaceEntry.COLUMN_PLACE_LONGITUDE + " VARCHAR, "+
PlaceContract.PlaceEntry.COLUMN_PLACE_IS_SELECTED + " VARCHAR, " +
PlaceContract.PlaceEntry.COLUMN_PLACE_ID + " TEXT NOT NULL, " +
"UNIQUE (" + PlaceContract.PlaceEntry.COLUMN_PLACE_ID + ") ON CONFLICT REPLACE" +
"); ";
please help me what I am doing wrong ....
The most common causes of column not found are typing errors and a misconception in regards to the onCreate method.
The former is unlikely if you are consistently using a single source for the column name e.g. if you use PlaceContract.PlaceEntry.COLUMN_PLACE_NAME to refer to the place_name column.
With the latter, the onCreate method only runs automatically when the database is created, any changes made to the schema, such as adding columns, will not be applied. Thus if you changed the CREATE SQL string to add the PLACE_NAME column that column will not be added.
When developing an App and when the data can be lost then then there are three quick ways to rectify the situation.
Delete the App's data and rerun (the database will be deleted (unless the database is stored outside of the App (not recommended and not the typical scenario))).
Uninstall the App and rerun (also delete's the App's data).
IF the onUpgrade will drop the said table or tables and then recreate the tables (generally by calling the onCreate method) then the database version can be increased (this is the 4th parameter of the super call when constructing the Database Helper class (i.e. the class that extends SQLiteOpenHelper)).
If the data in the database cannot be lost, then the alternative is to use the ALTER to add the column or to create another table, copy the data from the original table and then drop the original table and use ALTER to rename the new table to be the original table.

How do I create an SQL table only if it doesn't exist?

I am programming in Android and am trying to make an SQL database to store highscores. In my onCreate method, I have
String query = "CREATE TABLE " + TABLE_SCORES + "(" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_SCORE + " TEXT" + ");";
db.execSQL(query);
where TABLE_SCORES is the table name and the COLUMNS are my columns.
When I run the app, it works the first time and saves, but crashes the second time. In the logs, it says that it was unable to compile my query. I have already tried IF NOT EXISTS but it did not help.
Simply add IF NOT EXISTS after CREATE TABLE!
you should subclass SQLiteOpenHelper, implement public abstract void onCreate (SQLiteDatabase db), and put your create query there. onCreate is called just once, the first time the database is created. This way you can avoid checking if the table exits or not

is SQLite db remain after application shutdown?

Very (very) basic question that unclear to me:
Is SQLite db remain after application shutdown with all the data that was added to it or destroyed?
If so (and I hope so), when is the the DB schema created during the app lifecycle? I would expect it to be created on app installation,
but according to the documentation I see this is done every time that the application started.
What am I missing?
When is the code below executed during the application life cycle?
public class DatabaseHandler extends SQLiteOpenHelper {
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
+ KEY_PH_NO + " TEXT" + ")";
db.execSQL(CREATE_CONTACTS_TABLE);
}
} //DatabaseHandler
the DB data is stored under /data/data/<your.app.package.name>/database/ (or something similar to that). It is a physical file that remains stored on the device until your application is uninstalled or the user goes to Settings->App->Clear Data
the code you posted is executed the first time ever your app executes getReadableDatabase or getWritableDatabase. That means, the SQLiteOpenHelper class checks if a valid DB file exist on that location in disk. If there's no file, it executes the onCreate (which creates the DB file).
excerpt from methods getReadableDatabase or getWritableDatabase documentation:
Create and/or open a database
SQLite database will remain after shutdown.
Try use
CREATE TABLE IF NOT EXIST
to prevent the re-creation of the database
Yes, it remains until you remove your app from the smartphone or explicitly clear the DB.
You should check this tutorial, which covers a lot of sqlite for android.
Hope it helps.

how to skip creating table code if table exist in android

CREATE TABLE IF NOT EXISTS not working
Note : onCreate called only once when database created and when you change version number then it will call onUpgrade function.So don't worry it will create only once,anyway you may use
CREATE TABLE IF NOT EXIST will create the table if it doesn't exist, or ignore the command if it does.So change
String CREATE_LOGIN_TABLE = "CREATE TABLE LibLogin ( " + "id INTEGER PRIMARY KEY, " + "password TEXT, "+ "status TEXT )";
to
String CREATE_LOGIN_TABLE = "CREATE TABLE IF NOT EXISTS LibLogin ( " + "id INTEGER PRIMARY KEY, " + "password TEXT, "+ "status TEXT )";
onCreate will be called only once when you install your app first time. Onupgrade will be called if you change the version number of your DB, so it won't be executed everytime you run your applicacion (as Giru said) ;)
Take a look to your version number in your constructor and don't change it if you don't want re-create your DB.
why you don't work with online database and use json string for download date. in this way you can create web site and people use the service on pc and not only on android :)

How to do SQL Insert or Replace like operation without changing primary key?

I'm trying to insert a record into a SQLite database table. The table has a Unique constraint on a column "URL" and a primary key auto increment integer "_id".
I'm using insert or replace as my conflict resolution, since I need the new data to be persisted. However, this method is incrementing the primary key and messing up some foreign keys in other tables.
What's the best way to overwrite the record without updating the _id?
The simple answer is to stop using Replace syntax. This causes the old record to be deleted then a new one added ... which would increment your index.
Utilize the UPDATE syntax to handle conflicts instead
EDIT:
If you are really partial to the Replace syntax then it will come at a cost. You will need to write additional code that updates all prev occurrences of the old index to the new one. Not overly hard but this will correct the issue of synchronizing indexes
Documentation [Listed under REPLACE section little ways down the page]: http://www.sqlite.org/lang_conflict.html
this is my code of SQLite
"CREATE TABLE IF NOT EXISTS posts (" +
"_id integer NOT NULL," +
"id_language integer NOT NULL" +
");" +
"CREATE UNIQUE INDEX posts_idx ON posts(_id, id_language);";
"INSERT OR REPLACE INTO " + DB_TABLE + " (" + formulateColumns() + ") " +
"VALUES (" + formulateValues(v) + ");");

Categories

Resources