In Android 4.2, using SQLite 3.7.11, when I delete a row from the Quizzes table, who's schema is below, the corresponding rows in the QuizQuestions table are not deleted.
I can't figure out what's wrong. I have tried putting
db.execSQL("PRAGMA foreign_keys = ON;");
before and after the create table statements.
Create table statements:
CREATE TABLE quizzes(quiz_name TEXT PRIMARY KEY COLLATE NOCASE);
CREATE TABLE quizQuestions(quiz_name TEXT, question_id INTEGER,
PRIMARY KEY(quiz_name, question_id),
FOREIGN KEY(quiz_name) REFERENCES quizzes(quiz_name) ON DELETE CASCADE,
FOREIGN KEY(question_id) REFERENCES questions(question_id) ON DELETE CASCADE);
Your database should delete rows from quizQuestions in case someone is deleting from quizzes or from questions. It will ignore the entire foreign key constraint in case foreign key support is turned off and you have just regular columns that can contain any value.
SQLite defaults to PRAGMA foreign_keys = OFF every time you open the database. It's not a property of a table or of the schema.
In case you use SQLiteOpenHelper put it in onOpen. That is the place that is called every time the database is opened. onCreate only once when the database is created.
What SQLiteOpenHelper calls when you call getWriteableDatabase for the first time is
onConfigure every time, API Level >= 16 required
depending on the existence and version of the database file the following is called within an transaction
onCreate if there is no database file. Typically, this happens only once in the entire lifetime of the app.
onUpgrade if the database version (PRAGMA user_version - saved inside the database file) is less then the version supplied in SQLiteOpenHelper's constructor. Happens every time you bump the version in your code.
Nothing if file exists and version matches.
onOpen every time
If the same instance of SQLiteOpenHelper already has an open database it will just return it and nothing of above happens.
Try adding this right after opening database in your Android app:
db.execSQL("PRAGMA foreign_keys=ON");
This turns on support for foreign keys, which is necessary for ON DELETE CASCADE to work properly.
Sqlite disable foreign key constrain by default, so you need to enable it by simply override onOpen method in your DBhelper class like below
public class YourOwnDbHelper extends SQLiteOpenHelper {
#Override
public void onOpen(SQLiteDatabase db){
super.onOpen(db);
db.execSQL("PRAGMA foreign_keys=ON");
}
}
i had the same issue on visual basic!!! you have to write the command text like this:
cone.CommandText = "PRAGMA foreign_keys = ON; DELETE FROM employees
WHERE cod_emp=0;"
and you have to do it everytime you delete something
Related
I am working on a project on android where thousands of tables exist.Unfortunately I do not have fresh data base so what can I do to delete all record from all tables. i am using sqlite database .If it is possible please tell me.
If you want to remove the entire rows/data from table, then it's better to drop the table and recreate it. This is the usual convention and for this reason SqLiteOpenHelper has onCreate() and onUpgrade() method which creates table or upgrades it, when table is dropped, or database version is changed
For deleting/dropping table, the code fragment is
db.execSQL("DROP TABLE IF EXISTS " + YOUR_TABLE);
Check the first answer for reference What happens if an android app, which creates database, is then uninstalled?
I am creating Android application, and now I am stuck about proper DB design.
I have 3 tables in my local sqlite db:
BOXES
id
title
NOTES
id
title
content
BOXES_NOTES
id
box_id
element_id
type
Element ID is id for NOTES.id or BOXES.id and now I want to make it as foreign key, so when I delete entry in BOXES or NOTES, I want to update BOXES_NOTES table appropriately. How can I do it?
CREATE TABLE BOXES_NOTES(
ID .... REFERENCES NOTES(ID) ON DELETE /*your constraint*/
BOX_ID ... REFERENCES BOXES(ID) ON DELETE /*your constraint*/
... )
After ON DELETE you can add:
NO ACTION -> You can't delete a box row if there's at least one id into box_notes
CASCADE -> If you delete a box row all boxes_notes rows with that id will be deleted
SET NULL -> If you delete a box row all boxes_notes rows with that id will be set to null (if possible)
What said for ON DELETE is also valid for ON UPDATE.
Remember that using SQLite you have to abilitate foreign keys control. I suggest you to use a SQLiteOpenHelper and override the onOpen method like that:
public void onOpen(SQLiteDatabase db){
super.onOpen(db);
if (!db.isReadOnly()) {
// Enable foreign key constraints
db.execSQL("PRAGMA foreign_keys=ON");
}
}
Nevermind, I redesigned DB a little bit, so now I have only 2 tables:
BOXES
id
title
box_id
NOTES
id
title
content
box_id
Thank you all for answers.
[box_id] INTEGER CONSTRAINT [box_ref] REFERENCES [BOXES]([id]) ON DELETE CASCADE NOT NULL,
[element_id] INTEGER CONSTRAINT [notes_ref] REFERENCES [NOTES]([id]) ON DELETE CASCADE NOT NULL,
since we have cascade delete in both box_id and element_id, any entry in box or in notes deleted will cascade delete entry in this table
suggestion - use proper naming convention
instead of element_id name it notes__id (double underscore normally used to name foreign keys
for all these to work in sqlite one important thing is that we have to enable foreign key constraint at database level which is by default disabled in android
to enable foreign key constraint do the below
db.execSQL("PRAGMA foreign_keys=ON;");
I have an app released in app store
I want to add a new column to the user table in the sqlite db and want it to be not null
But I also want old users to be able to use the app
What will happen if an old user updates their app with the new version? At login, I get the info from the server and I insert it in the db. The db insertion will probably stop when there is no value for the new column
Also, how do I do the upgrade itself?
in onUpgrade I do "ALTER table USER..."
in the constructor of the SQLite helper I add the new DB version
what else?
Also, I've added 3-4 totally new tables needed for new features. I've called their create queries in the onCreate method of the SQLite helper. Should I do anything else in addition to this?
in the constructor of the SQLite helper I add the new DB version
That will trigger onUpgrade(), good.
However, you cannot use ALTER TABLE to add a column with NOT NULL.
Here's what you can do in onUpgrade() to preserve user data:
Rename the old table to a temporary name
Recreate the table with the new column and NOT NULL
Populate the new table from the old temp table and supply the new column a reasonable non-null default value
Drop the temporary table
Can you give me an example lets say table is called USER with fields NAME and EMAIL and now I want to add a new field AGE?
Here's an example:
sqlite> create table user(name, email);
sqlite> insert into user select 'foo','bar';
sqlite> alter table user rename to user_temp;
sqlite> create table user(name, email, age not null);
sqlite> insert into user select name,email,-1 from user_temp;
sqlite> drop table user_temp;
sqlite> select * from user;
name|email|age
foo|bar|-1
Also, I've added 3-4 totally new tables needed for new features. I've called their create queries in the onCreate method of the SQLite helper. Should I do anything else in addition to this?
should I put the new creates for the new tables in both onCreate and onUpgrade or only in onUpgrade?
Make sure the same new tables are created in onUpgrade().
onCreate() is only run when the database is created for the first time, not on upgrade.
After both onCreate() and onUpgrade() the database schema (table structure) should be compatible. How you implement it is up to you. Putting the CREATE TABLEs there in onUpgrade() is an option. Some people prefer to call onCreate() insinde onUpgrade(), which can cause some headache when trying to migrate old data.
About the update of SQLite in Android.When you change the structure of the datebase,how can we update the datebase without delete the data?
You should override the onUpgrade Method in the SQLiteOpenHelper. You should code something like this.
public void onUpgrade (SQLiteDatabase db,int oldVersion,int newVersion){
String update = ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>;
db.execSQL(update);
}
Dropping a table, adding a row, inserting/updating/deleting data should be done here.
Alter Table gives you very limited options in performing an update to the database tables. If you want to copy your data into a completely new structure, you should think about creating temporary tables where you can copy data, create the new schema and then copy your data from the temporary tables to the new table, in this upgrade method.
Make sure you have your DB Version numbers correctly updated while creating the DBHelper.
i am getting information from user in sqlite database.
But when i insert same record which is already in database it is added again.
how i can stop duplication of record in sqlite. I am developing this in android.
I am using mobile number as primary key. still it add that record in database.
Please suggest me appropriate solutions.
Thanks in advanced.
Be aware of the limitations of REPLACE or INSERT OR REPLACE as these will overwrite any custom data your app user has added to these rows in the database - it is not as advanced as UPSERT in other SQL databases.
As mentioned in a previous post you really need to identify what the primary key could be and use this information to either update old data or to remove an old row before inserting the fresh one.
If this is not possible then you could always DELETE FROM my_table or DROP my_table before running the insertions so that there will be no duplicates. This will (for better or worse) also make sure that data that is missing from new imports is not left lying around in your app.
make sure you have set your phone number as Primary Key at the time you created the table.
for example:
String query = "CREATE TABLE IF NOT EXISTS PhoneBook ("+
"TelNum VARCHAR(100) PRIMARY KEY NOT NULL,"+
"Address TEXT);";
db.execSQL(query);
and in case you want to enforce foreign keys defined in your table then call the following method before doing anything in your database
db.execSQL("PRAGMA foreign_keys = ON;"); //enforcing FK
Use REPLACE INTO keyword:
REPLACE INTO my_table (pk_id, col1) VALUES (5, '123');
This automatically identifies the primary key and finds a matching row to update, inserting a new one if none is found.