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?
Related
I use Sqlite and I have the following DB , I am developing an application for women which it should contain a login and sign up . I had problems in the database like "no such column"
DataBase
public class DB_MJG extends SQLiteOpenHelper {
public static final String name ="dataB.db";
public static final int version =1;
//Les atts de la table FEMME
public static final String table_Femme ="Femme";
public static final String ID_F = "id";
public static final String NOM_F ="nom";
public static final String PRENOM_F="prenom";
public static final String PSEUDO="pseudo";
public static final String MDP="mdp";
public static final String GRP_F="grpSang";
public static final String AGE_F="age";
public static final String POIDS="poids";
public DB_MJG( Context context) {
super(context, name, null, version);
}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE_FEMME = "CREATE TABLE " + table_Femme + "(
"+ID_F+" INTEGER PRIMARY KEY AUTOINCREMENT, "
+NOM_F+" TEXT, "+PRENOM_F+" TEXT " + ")";
db.execSQL(CREATE_TABLE_FEMME);
System.out.println("table femme crée");
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS "+table_Femme);
db.execSQL("DROP TABLE IF EXISTS "+table_Enfant);
}
//insérer dans la table FEMME
public void insertFemme(Femme f)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues vals = new ContentValues();
vals.put(NOM_F,f.getNom());
vals.put(PRENOM_F,f.getPrenom());
db.insert(table_Femme,null,vals);
db.close();
}
public ArrayList getFemme()
{
ArrayList<Femme> femmes = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM " +table_Femme, null);
while(c.moveToNext()){
Femme f = new Femme(c.getString(1),c.getString(2));
femmes.add(f);
}
return femmes;
}
}
Launcher Activity
public class MainActivity extends AppCompatActivity {
DB_MJG db = new DB_MJG(this);
SQLiteDatabase database ;
String s = "";
private Button log,sign;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
database = openOrCreateDatabase(db.name, Context.MODE_PRIVATE, null) ;
db.insertFemme(new Femme("sara","sara"));
ArrayList<Femme> femmes = db.getFemme();
TextView textView= (TextView) findViewById(R.id.textView13);
for(Femme f : femmes){
String ch = "Nom :" +f.getNom() + " Prenom : "
+f.getPrenom()+"\n";
s = s +ch;
}
textView.setText(s);
}
Error
E/SQLiteLog: (1) table Femme has no column named nom
E/SQLiteDatabase: Error inserting nom=sara prenom=sara
android.database.sqlite.SQLiteException: table Femme has no column named
nom (code 1 SQLITE_ERROR): , while compiling: INSERT INTO
Femme(nom,prenom) VALUES (?,?)
at
android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native
Method)
When I compile,it says no such column. I have defined the nom column. The database has the nom that I am trying to use for inserting but it doesn't work.
The primary issue you have is that the database helper's onCreate method is only called when the database is created, which is once in it's lifetime.
As such if any changes are made to the structure (schema) by amending the create table SQL, as used in the onCreate method, they will not be reflected unless the database is deleted or that the onCreate method is invoked some other way.
Often such changes, as least when developing the app, are applied by first doing one of the following :-
Deleting the App's data (this deletes the database, so onCreate is automatically called).
Uninstalling the App (and as a result deletes the App's data).
IF the onUpgrade method is written to drop the changed table(s) and recreate the tables (often/generally by calling the onCreate method)
After doing one of the above, rerunning the App will then result in the structure change being applied.
Note the above will result in the loss of existing data and IS NOT SUITABLE for an App that has been deployed.
In your case if using option 3, the onUpgrade method needs to include the creation of the table(s) after they have been dropped as it only drops the tables.
You code in the MainActivity is also overly complex in that it utilises opening the database without using the SQLiteOpenHelper to open the database but rather opens it using the SQLiteDatabase openOrCreate method (which doesn't result in the SQLiteOpenHelper's (DB_MJG is a subclass of SQLiteOpenHelper) onCreate method being called). However, by a quirk/luck, when you do start to use the instance of DB_MJG, namely db, as the instance was created before openOrCreate method, it actually goes on to call the onCreat method.
However, it would be much simpler, to just use one method to open the database.
As such I'd suggest implementing using just the DB_MJG DatabseHelper.
Fix
The essential fix, is to introduce the changed structure. So one of the 3, above should be taken.
if using 3. then amending the onUpgrade method to call the onCreate method and then increasing the version number would be required. That is the onUpgrade method could be :-
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS "+table_Femme);
db.execSQL("DROP TABLE IF EXISTS "+table_Enfant);
onCreate(db); //<<<<<<<<<< ADDED so that onUpgrade creates the tables after they have been dropped
}
Additional/Recommended
Close Cursor
in DB_MJG.java the getFemme method leaves the Cursor open. This can result in a too many open databases or cursors excpetion so it is suggested that the line :-
c.close();
is added to the getFemme method, so it becomes :-
public ArrayList getFemme()
{
ArrayList<Femme> femmes = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM " +table_Femme, null);
while(c.moveToNext()){
femmes.add(new Femme(c.getString(c.getColumnIndex(NOM_F)),c.getString(c.getColumnIndex(PRENOM_F))));
}
c.close(); //<<<<<<<<<< should always close a cursor when finished with it
return femmes;
}
Note the above also does away with the need for the intermediate Femme object f.
Use DB_MJG to open the database
There is no need to openOrCreate the database when using a subclass of SQliteOpenHelper as it will do this. So MainActivity.java could be :-
public class MainActivity extends AppCompatActivity {
DB_MJG db; // Only declare the DB_MJG object.
private Button log,sign;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new DB_MJG(this);
db.insertFemme(new Femme("sara","sara"));
ArrayList<Femme> femmes = db.getFemme();
TextView textView= (TextView) findViewById(R.id.textView13);
StringBuilder sb = new StringBuilder(); //<<<<<<<<<< ADDED - Use StringBuilder in a loop
for(Femme f : femmes){
sb.append("Nom: ").append(f.getNom()).append(" Prenom: ").append(f.getPrenom());
}
textView.setText(sb.toString());
}
}
Note that the above should be changed at the same time or after the fix has been applied.
Instead of concatenating Strings in a loop a StringBuilder has been used. See -Why to use StringBuffer in Java instead of the string concatenation operator
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 have a simple game where users guess words. Now, I'm thinking using database to store these words to be guessed.
My problem is the tutorials that are available in the web show how to create a database and save user inputs to that database. They create, for example, a DBHelper.java in src, extends it to SQLiteOpenHelper, override the methods. Back to a specific activity, create an instance of DBHelper, then create the db, open the writable, insert user inputs, close db.
But what I think I only need to do is create a database, insert words in it, then make my app retrieve words from this database.
Am i just wondering if what i'm planning to do is right:
1. create a DBHelper.java in src, extends the class to SQLiteOpenHelper
2. define needed Strings like name of database etc.
3. Create a constructor and override the onCreate and onUpgrade methods
4. CREATE A LOADWORDS METHOD this is where i will insert my words to the database.
5. on my main activity(the first screen on my app) I will create an instance of DBHelper and call the onCreate and loadWords method.
// you would want an onCreate and onUpgrade method for best practices,, here's a partial look of what you want...
public class DBManager extends SQLiteOpenHelper
{
static final String TAG = "DBManager";
static final String DB_NAME = "words.db";
static final int DB_VERSION = 1;
static final String TABLE = "words_table";
static final String C_ID = "id";
static final String C_WORD = "word";
public DBManager(Context context)
{
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
String sql = "CREATE TABLE " + TABLE + " ("
+ C_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ C_WORD + " TEXT)";
db.execSQL(sql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSQL("DROP TABLE IF EXISTS " + TABLE);
onCreate(db);
}
//**** Code Insert Word and Retrieve Word Methods *****//
//**** End Code Insert Word and Retrieve Word Methods *****//
}
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.
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