Sqlite column fails to create in creation time - android

I'm facing a strange problem. I'm creating a db in sqlite with the below query
String GROUP_TABLE = "groups";
String ROW_ID = "rowid";
String GROUP_ID = "GroupID";
String GROUP_NAME = "GroupName";
String GROUP_STATUS = "GroupStatus";
String IS_ADMIN = "IsAdmin";
String GROUP_TYPE = "GroupType";
String IS_PUBLIC = "IsPublic";
String LAST_UPDATE = "LastUpdate";
String groupQuery = "CREATE TABLE IF NOT EXISTS "+ GROUP_TABLE +" ("
+ROW_ID+" INTEGER PRIMARY KEY, "
+GROUP_ID+" TEXT, "
+GROUP_NAME+" TEXT, "
+GROUP_STATUS+" TEXT, "
+GROUP_TYPE+" TEXT, "
+IS_ADMIN+" TEXT, "
+IS_PUBLIC+" TEXT, "
+LAST_UPDATE+" TEXT);";
This is the schema given by sqlite adb command
H:\adt-bundle-windows-x86_64-20140702\sdk\platform-tools>sqlite3
SQLite version 3.8.10.2 2015-05-20 18:17:19
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .open mydb.db
sqlite> .full schema
Usage: .fullschema
sqlite> .fullschema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE groups (rowid INTEGER PRIMARY KEY, GroupID TEXT, GroupName TEXT, GroupStatus TEXT, GroupType TEXT, IsAdmin TEXT, IsPubli
c TEXT, LastUpdate TEXT);
/* No STAT tables available */
and when I enter records for the first time there will be no problem. But when I try to enter records next time i get
E/SQLiteLog﹕ (1) table groups has no column named LastUpdate
11-04 14:35:01.850 11947-11974/? E/SQLiteDatabase﹕ Error inserting GroupType=1 GroupID=553 LastUpdate=2015-08-08T14:17:14.000Z IsAdmin=1 GroupName=SAIFOOTWEARS GroupStatus=1
android.database.sqlite.SQLiteException: table groups has no column named LastUpdate (code 1): , while compiling: INSERT INTO groups(GroupType,GroupID,LastUpdate,IsAdmin,GroupName,GroupStatus) VALUES (?,?,?,?,?,?)
And when I check the schema again the column is missing.
H:\adt-bundle-windows-x86_64-20140702\sdk\platform-tools>sqlite3
SQLite version 3.8.10.2 2015-05-20 18:17:19
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .open mydb.db
sqlite> .fullschema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE groups ( rowId INTEGER PRIMARY KEY,GroupID TEXT, GroupName TEXT,GroupStatus TEXT,IsAdmin TEXT, GroupType TEXT, IsPublic
TEXT);
/* No STAT tables available */
Any leads on this would be of great help.

onCreate() method of sqliteOpenHelpers called when the database is created for the first time. This is where the creation of tables and the initial population of the tables should happen.
I think first time when you created your database you don't include LastUpdate column. Later you included it.but your table is created first time.So when adb get same database version for your app it dose not update your database.
So try this
Change your databse version no. Or uninstall app from your phone and run it again.
If problem does not solve.Then please provide full code of your class in Question.

Related

Android - Change a column type in SQLite database dynamically at runtime

I have an application, where I am detecting the type of a particular column at run-time, on page load. Please refer the below code:
public String fncCheckColumnType(String strColumnName){
db = this.getWritableDatabase();
String strColumnType = "";
Cursor typeCursor = db.rawQuery("SELECT typeof (" + strColumnName +") from tblUsers, null);
typeCursor.moveToFirst();
strColumnType = typeCursor.getString(0);
return strColumnType;
}
The above method simply detects the type of column with column Name 'strColumnName'. I am getting the type of column in this case.
Now, I want to change the column type to TEXT if I am receiving INTEGER as the column type. For this, I tried the below code:
public String fncChangeColumnType(String strColumnName){
db = this.getWritableDatabase();
String newType = "";
Cursor changeCursor = db.rawQuery("ALTER TABLE tblUsers MODIFY COLUMN " + strColumnName + " TEXT", null);
if (changeCursor != null && changeCursor.moveToFirst()){
newType = changeCursor.getString(0);
}
return newType;
}
But while executing the 'fncChangeColumnType' method, I am getting this error, android.database.sqlite.SQLiteException: near "MODIFY": syntax error (code 1): , while compiling: ALTER TABLE tblUsers MODIFY COLUMN UserID TEXT
NOTE: I also replaced 'MODIFY' with 'ALTER', but still getting the same error.
Please check if this is the right method to change the type dynamically.
Please respond back if someone has a solution to this.
Thanks in advance.
In brief, the solution could be :-
Do nothing (i.e. take advantage of SQLite's flexibility)
you could utilise CAST e.g. CAST(mycolumn AS TEXT) (as used below)
Create a new table to replace the old table.
Explanations.
With SQLite there are limitations on what can be altered. In short you cannot change a column. Alter only allows you to either rename a table or to add a column. As per :-
SQL As Understood By SQLite - ALTER TABLE
However, with the exception of a column that is an alias of the rowid column
one defined with ?? INTEGER PRIMARY KEY or ?? INTEGER PRIMARY KEY AUTOINCREMENT or ?? INTEGER ... PRIMARY KEY(??) (where ?? represents a valid column name)
you can store any type of value in any type of column. e.g. consider the following (which stores an INTEGER, a REAL, a TEXT, a date that ends up being TEXT and a BLOB) :-
CREATE TABLE IF NOT EXISTS example1_table (col1 BLOB);
INSERT INTO example1_table VALUES (1),(5.678),('fred'),(date('now')),(x'ffeeddccbbaa998877665544332211');
SELECT *, typeof(col1) FROM example1_table;
The result is :-
As such is there a need to change the column type at all?
If the above is insufficient then your only option is to create a new table with the new column definitions, populate it if required from the original table, and to then replace the original table with the new table ( a) drop original and b)rename new or a) rename original, b) rename new and c) drop original)
e.g. :-
DROP TABLE IF EXISTS original;
CREATE TABLE IF NOT EXISTS original (mycolumn INTEGER);
INSERT INTO original VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(0);
-- The original table now exists and is populated
CREATE TABLE IF NOT EXISTS newtable (mycolumn TEXT);
INSERT INTO newtable SELECT CAST(mycolumn AS TEXT) FROM original;
ALTER TABLE original RENAME TO old_original;
ALTER TABLE newtable RENAME TO original;
DROP TABLE IF EXISTS old_original;
SELECT *,typeof(mycolumn) FROM original;
The result being :-
i think the sql query statement is wrong ,try
ALTER TABLE tblUsers MODIFY COLUMN id TYPE integer USING (id::integer);
instead of id use column name....
hope this helps....
EDIT:
"ALTER TABLE tblUsers MODIFY COLUMN "+strColumnName+" TYPE integer USING ("+strColumnName+"::integer);"

If table already exists do not insert rows and give toast

I have an app that allows the user to save some chosen rows from a temporary table. The user is able to name the new table.
I am successfully creating a table using the name the user has input, and putting all the chosen rows from the temporary table into the new table.
However, if the table name they enter already exists, I want to notify them via Toast and have them choose another name. I am still learning sqlite - is there a way to do this?
In my head I am using some sort of if statement to check if the table exists, and then executing code, however half of it is in sqlite and half is in java. I'm not sure the correct way to do this. Any suggestions are greatly appreciated!
private void createTable() {
dbHandler.getWritableDatabase().execSQL("CREATE TABLE IF NOT EXISTS " + favoriteName + " ( _id INTEGER PRIMARY KEY AUTOINCREMENT , exercise TEXT , bodypart TEXT , equip TEXT );");
dbHandler.getWritableDatabase().execSQL("INSERT INTO " + favoriteName + " SELECT * FROM randomlypicked");
Try
Cursor cursor = dbHandler.getReadableDatabase().rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName +"'", null);
if(cursor!=null) {
if(cursor.getCount()>0) { //table already exists
//show toast
cursor.close();
return;
}
cursor.close();
}
//create table and insert normally

creating two tables in android app database

I'm trying to create two tables in my android app database and the application crashes when i'm tring to insert values to the first table, but when i delete the database and recreate it only with one table, it works fine. i don't get it?
the code is:
private static String query_create_user = "CREATE TABLE User ( email TEXT PRIMARY KEY, firstName TEXT, lastName TEXT, password TEXT)";
private static String query_create_group = "CREATE TABLE Group ( groupNumber INTEGER PRIMARY KEY AUTOINCREMENT, courseNumber INTEGER, groupName TEXT, groupType TEXT, groupOwner TEXT)";
public SchoolBagDataBase (Context applicationcontext) {
super(applicationcontext, "contract.db", null, 1);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(query_create_user);
database.execSQL(query_create_group);
}
thanks in advance!
The SQL statement held in string 'query_create_group' is invalid. You can't have a table called Group because GROUP is a reserved word in SQLite. Just choose a different name for your table.

SQLite connection:application stops working

I am making a diary application in android which is supposed to get some data from text fields.
When I run my app on the emulator, it gets successfully installed but as soon as I give input in the fields and I tap save option in the menu, emulator prompts that diary app has stopped working.
I am not able to find database folder in my app in emulator's file explorer which means my database is not making.
Here is my SQLite connection making and insertion in table code that i am writing in save item.
if(item.getItemId()==R.id.save){
EditText et=(EditText)findViewById(R.id.mood);
String mood=et.getText().toString();
et= (EditText)findViewById(R.id.weather);
String weather=et.getText().toString();
et= (EditText)findViewById(R.id.Text);
String text=et.getText().toString();
Date date= new Date();
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strDate = sdfDate.format(date);
SQLiteDatabase db= openOrCreateDatabase("DiaryDatabase",MODE_PRIVATE,null);
db.execSQL("CREATE TABLE IF NOT EXIST DIARY ('Mood VARCHAR' , 'Weather VARCHAR' , 'Text VARCHAR' , 'Time VARCHAR' , 'Id INTEGER PRIMARY KEY');");
db.execSQL("INSERT INTO DIARY VALUES(mood,weather,text,strDate,NULL);");
db.close();
}
I think your both e.q. DDL and DML statement is incorrect. Try to replace yours with following:
String createQuery = "CREATE TABLE IF NOT EXIST DIARY ("
+ "id integer primary key, "
+ "mood text, "
+ "weather text, "
+ "content text, "
+ "time text" + ")";
Here:
INSERT INTO DIARY VALUES(mood,weather,text,strDate,NULL);
Your origin create statement create PK column as last column and here in your insert statement you are trying to insert NULL as PK that is not allowed and it doesn't make sence since PK is unique identifier of each row.
You should create a SQLite helper class extending from SQLiteOpenHelper to perform all of the database related items such as creating the database and creating the required tables.
Check out this example and use it as a guide:
http://www.vogella.com/articles/AndroidSQLite/article.html

SQLite and Android Insert/Updates on SQLiteDatabase -CompiledStatements-

Pretend I have a table with 2 columns. _id and name. _id is the primary key and I do not want to set this value manually. I want to perform an insert of name="john," and let the program create my own _id. I am unclear what "index" to use when inserting and how many question marks to use. Does this code do the job? Should the index for john be 1 or 2?
String TABLENAME = "table";
SQLiteStatement statement = db.compileStatement("INSERT INTO "+TABLENAME+" VALUES(?);");
statement.bindString(1,"john");
statement.executeInsert();
Next, say I want to manually set my own _id value. Would I change the code to:
String TABLENAME = "table";
SQLiteStatement statement = db.compileStatement("INSERT INTO "+TABLENAME+" VALUES(?,?);");
statement.bindLong(1,666); //Manual _id.
statement.bindString(2,"john");
statement.executeInsert();
Your first example where you provide only the name will not work:
sqlite> create table test (i integer primary key autoincrement, j text);
sqlite> insert into test values ('asd');
Error: table test has 2 columns but 1 values were supplied
sqlite> insert into test values (null, 'asd');
sqlite> select * from test;
1|asd
sqlite> insert into test (j) values ('asd');
sqlite> select * from test;
1|asd
2|asd
so you need to identify the name column as the destination of the sole value this way, (or as you mentioned in your comment pass null):
SQLiteStatement statement = db.compileStatement("INSERT INTO "+TABLENAME+" (name) VALUES(?);");
Your second example should work fine.
This would apply to some table created this way:
create table SomeTable (_id integer primary key autoincrement, name text)
Then
SQLiteStatement statement = db.compileStatement("INSERT INTO "+TABLENAME+" VALUES(null,?);");
statement.bindString(1,"john");
Should also work.

Categories

Resources