Delete duplicated content in table - sqlite

I've a Table table_news containing these fields :
_ID = INTEGER PRIMARY KEY AUTOINCREMENT
ID = TEXT NOT NULL
CONTENT = TEXT NOT NULL
ZONE TEXT = NOT NULL
AREA TEXT = NOT NULL
TITLE TEXT = NOT NULL
DATE TEXT = NOT NULL
AUTHOR TEXT = NOT NULL
This table is filled like below:
Column Row 1 Value Row 2 Value
------------------------------------------------------
_ID 1 2
ID "5" "5"
CONTENT "Discover New York." "Discover New York."
ZONE "New York" "New York"
AREA "New York" "New York"
TITLE "Let's discover the world." "Let's discover the world."
DATE "2012-07-04" "2012-07-04"
AUTHOR "Henry Brakman" "Henry Brakman"
So I just want to make an SQL statement in order to delete one of these duplicated rows.
I tried this (line breaks added for ease of reading, command is written as single string):
public SQLiteStatement removeSameContentNews() {
return bdd.compileStatement("DELETE FROM table_news "
+ "WHERE _ID NOT IN (SELECT MIN( _ID) "
+ "FROM table_news "
+ "GROUP BY ID, CONTENT, ZONE, AREA, TITLE, DATE, AUTHOR)");
}
But this deleted nothing..
I finally used uniqueness with UNIQUE keyword and it's working properly:
private static final String CREATE_TABLE_NEWS =
"CREATE TABLE " + TABLE_NEWS + " (" + COLUMN_ROWID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + COL_ID
+ " TEXT NOT NULL UNIQUE, " + COL_CONTENT
+ " TEXT NOT NULL, " + COL_ZONE + " TEXT NOT NULL, "
+ COL_AREA + " TEXT NOT NULL, " + COL_TITLE
+ " TEXT NOT NULL, " + COL_DATE + " TEXT NOT NULL, "
+ COL_AUTHOR + " TEXT NOT NULL);";

You can use this example of query:
DELETE FROM table WHERE _ID NOT IN (
SELECT MIN( _ID)
FROM table
GROUP BY ID, CONTENT, ZONE, AREA, TITLE, DATE, AUTHOR
)
EDIT
Alternatively you could use :
DELETE FROM table_news WHERE EXISTS
(SELECT 1 FROM table_news t
WHERE t.ID=table_news.ID AND
t.ID=table_news.CONTENT AND
t.ID=table_news.ZONE AND
t.ID=table_news.AREA AND
t.ID=table_news.TITLE AND
t.ID=table_news.DATE AND
t.ID=table_news.AUTHOR AND
t.rowid > table_news.rowid)

Related

Referenced foreign key id is null when inserting new values in the second table. How do I simply select the id from the first table to the second?

I have created two tables in my Database Manager
#Override
public void onConfigure(SQLiteDatabase db) {
db.setForeignKeyConstraintsEnabled(true);
super.onConfigure(db);
}
#Override
public void onCreate(SQLiteDatabase database)
{
database.setForeignKeyConstraintsEnabled(true);
// create table
String sql = "create table "
+ TABLE_NAME + " ("
+ C_LIST_ID + " integer primary key autoincrement, "
+ C_LIST_NAME + " VARCHAR(255))";
Log.d(TAG, "in onCreate");
//create second table
String sql2 = "create table "
+ TABLE_NAME_ITEMS + " ("
+ C_LIST_ITEM + " VARCHAR(255), "
+ C_DATE + " text, "
+ C_FLAG + " integer, "
+ C_LIST_NAME + " VARCHAR(255), "
+ C_ITEM_ID + " integer, foreign key "
+ "("+C_ITEM_ID+")" + " references " +TABLE_NAME+ "("+C_LIST_ID+"))";
Log.d(TAG, "in onCreate second database");
database.execSQL(sql);
database.execSQL(sql2);
}
This is how I am inserting the data into the second table. In the tables themselves, the foreign key IDs are null. How do I bring the id from the first table to the second when creating a new item with the same C_LIST_NAME?
public void insertItemData(String item, String listName)
{
Integer listNameId = getListId(listName);
database = getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(C_LIST_ITEM, item + listNameId);
contentValues.put(C_LIST_NAME, listName);
database.insertOrThrow(TABLE_NAME_ITEMS, null , contentValues);
Log.d(TAG, "insertData: data has been inserted in items");
}
I should've rested last night after trying to figure this out for hours.
I figured it out and the solution was very simple. I was just too tired to think I guess.
In case anyone is curious, I just need to insert it like this:
public void insertItemData(String item, String itemDescription, String listName)
{
baseActivity = new BaseActivity();
database = getWritableDatabase();
database.execSQL("INSERT INTO "+TABLE_NAME_ITEMS+
"("+C_ITEM_NAME+"," +C_ITEM_DESCRIPTION+ ", " +C_LIST_NAME+ "," +C_DATE+ "," +C_FLAG+ "," +C_ITEM_ID+ ")"
+ "VALUES ('"+item+ "', '"+itemDescription+ "', '" +listName+ "', '" +baseActivity.getCurTime()+ "', '" +0+ "', "
+ "(SELECT " +C_LIST_ID+ " FROM " +TABLE_NAME+ " WHERE "
+C_LIST_NAME+ "=?))",
new Object[]{listName});
Log.d(TAG, "insertData: data has been inserted in items");
}

android.database.sqlite.SQLiteException: no such column error even if column exists

I know this question has been asked multiple times, but there is something wrong in my syntax and I can't figure out what. This is the method that adds my column:
Property declaration:
public static final String COLUMN_TS_MILIS = "ts_milis";
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_PRODUCT + " TEXT, " +
COLUMN_PRICE + " TEXT, " +
COLUMN_TS + " TIMESTAMP DEFAULT CURRENT_TIMESTAMP," +
COLUMN_TS_MILIS + "timestamp integer default (cast(strftime('%s', 'now') as int))" +
");";
db.execSQL(query);
and this is the query that triggers the error:
Cursor totalCof = db.rawQuery("SELECT sum(" + COLUMN_PRICE + ")" + " FROM " + TABLE_NAME
+ " WHERE " + COLUMN_TS_MILIS + "= date('now')", null);
What is wrong in my syntax? Many thanks for help!
For the column that is meant to be named as per COLUMN_TS_MILIS, have omitted a space between the column name and the column type and hence the column name is a concatenation of the column name and column type. So assuming COLUMN_TS_MILIS resolves to millis then the QL will be :-
`CREATE TABLE ......,millistimestamp integer default (cast(strftime('%s', 'now') as int))`
instead of
`CREATE TABLE ......,millis timestamp integer default (cast(strftime('%s', 'now') as int))`
Additionally you have specified two types, timestamp and also integer, this won't be an issue SQLIite wise but may lead to confusion.
As such you probably just want
`CREATE TABLE ......,millis integer default (cast(strftime('%s', 'now') as int))`
As such you probably want to use :-
String query = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
COLUMN_ID + " INTEGER PRIMARY KEY, " +
COLUMN_PRODUCT + " TEXT, " +
COLUMN_PRICE + " TEXT, " +
COLUMN_TS + " TIMESTAMP DEFAULT CURRENT_TIMESTAMP," +
COLUMN_TS_MILIS + " INTEGER DEFAULT (cast(strftime('%s', 'now') as int))" +
");";
Note AUTOINCREMENT has been removed as you almost certainly don't need it as it has overheads.
To implement the change, you would have to drop the table, as it exists. The easiest way to do this is to either :-
delete the App's data or
uninstall the App
and then rerun the App (assuming that existing, if any, data can be lost).

Adding items to a second table SQLite in Android Studio does nothing

I think my problem is simple and I'm not being able to see the solution, but, when I add data to my second table it does nothing but showing the Toast that it is not working.
This is my DatabaseHelper.java:
#Override
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + TABLE_NAME + " ( " + COL1 + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COL2 + " TEXT);";
String createTable2 = "CREATE TABLE " + TABLE_NAME2 + " ( " + COL3 + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COL4 + " TEXT,"
+ COL5 + " INTEGER," + COL1 + " INTEGER PRIMARY KEY," + COL6 + " TEXT, " + " FOREIGN KEY (" + COL1 + ") REFERENCES "
+ TABLE_NAME + "(" + COL1 + "));";
db.execSQL(createTable);
db.execSQL(createTable2);
}
public boolean addData2(String newEntry1, String newEntry2, String horarios, Integer id_ppl) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL4, newEntry1);
contentValues.put(COL5, newEntry2);
contentValues.put(COL1, id_ppl);
contentValues.put(COL6, horarios);
long result = db.insert(TABLE_NAME2, null, contentValues);
if (result == -1) {
return false;
} else {
return true;
}
This is my mainactivity.java
buttonNewPill.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String newEntry1 = editText2.getText().toString();
String newEntry2 = editText3.getText().toString();
String textSp1 = spinner2.getSelectedItem().toString();
String textSp2 = spinner3.getSelectedItem().toString();
String horario = textSp1 + ":" + textSp2;
Integer id_ppl = 1;
Toast.makeText(getApplicationContext(), "horario is "+ horario, Toast.LENGTH_LONG).show();
/*
Toast.makeText(getApplicationContext(), "text is "+ textSp, Toast.LENGTH_LONG).show();
*/
if (editText2.length() > 0 && editText3.length() > 0){
AddData2(newEntry1, newEntry2, horario, id_ppl);
editText2.setText("");
editText3.setText("");
} else {
toastMessage("Isn't your field empty?");
}
}
});
private void AddData2(String newEntry1, String newEntry2, String horario, Integer id_ppl) {
boolean insertData = mDatabaseHelper.addData2(newEntry1, newEntry2, horario, id_ppl);
if (insertData){
toastMessage("Data Succesfully entered");
} else {
toastMessage("Oops! Something went wrong");
}
}
All classes are well acommodated, the contructors were made, and it doesn't have any syntaxes error (I think), since it lets me execute my app in my telephone. But I got the problem described above.
Thank you very much for your time and assistance in this matter.
Your, I believe, issue is that you are trying to define multiple PRIMARY INDEXES for the 2nd table.
That is you have :-
for COL3 INTEGER PRIMARY KEY AUTOINCREMENT
for COL1 INTEGER PRIMARY KEY
You can only have a single PRIMARY INDEX (you can have multiple non-primary indexes).
If you looked at the log, you would have had something similar to (when you first ran):-
05-11 01:38:10.133 1215-1215/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{soanswers.soanswers/soanswers.soanswers.MainActivity}: android.database.sqlite.SQLiteException: table "tbl002" has more than one primary key (code 1): , while compiling: CREATE TABLE tbl002 ( column3 INTEGER PRIMARY KEY AUTOINCREMENT, column4 TEXT,column5 INTEGER,column1 INTEGER PRIMARY KEY,column6 TEXT, FOREIGN KEY (column1) REFERENCES tbl001(column1));
So at a guess you would want :-
String createTable2 = "CREATE TABLE " + TABLE_NAME2 + " ( " +
COL3 + " INTEGER PRIMARY KEY, " +
COL4 + " TEXT,"
+
COL5 + " INTEGER," +
COL1 + " INTEGER," +
COL6 + " TEXT, " +
" FOREIGN KEY (" + COL1 + ") REFERENCES " + TABLE_NAME + "(" + COL1 + "));";
Column 1 removed as primary index, although you may want an additional index on COL1 as it references another table.
You very likely don't really want AUTOINCREMENT, as per
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.SQLite Autoincrement
Note that you will need to delete the App's Data or uninstall the App (as long as you can afford to lose any existing data) after making the changes, for the changes to be applied
- There are other ways but this is the simplest.
Adding the Index (optional):-
The following would add an additional index according to table2 col1 :-
#Override
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + TABLE_NAME + " ( " + COL1 + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COL2 + " TEXT);";
/*
String createTable2 = "CREATE TABLE " + TABLE_NAME2 + " ( " + COL3 + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COL4 + " TEXT,"
+ COL5 + " INTEGER," + COL1 + " INTEGER PRIMARY KEY," + COL6 + " TEXT, " + " FOREIGN KEY (" + COL1 + ") REFERENCES "
+ TABLE_NAME + "(" + COL1 + "));";
*/
String createTable2 = "CREATE TABLE " + TABLE_NAME2 + " ( " +
COL3 + " INTEGER PRIMARY KEY, " +
COL4 + " TEXT,"
+
COL5 + " INTEGER," +
COL1 + " INTEGER," +
COL6 + " TEXT, " +
" FOREIGN KEY (" + COL1 + ") REFERENCES " + TABLE_NAME + "(" + COL1 + "));";
String crtTable2Col1Index = "CREATE INDEX IF NOT EXISTS col1index ON " +
TABLE_NAME2 + "(" + COL1 + ")"; //<<<< ADDED
db.execSQL(createTable);
db.execSQL(createTable2);
db.execSQL(crtTable2Col1Index); //<<<< ADDED
}
col1index would be the name of the index
Additional
Note as you intend to utilise FOREIGN KEYS you will need to enable FOREIGN KEYS (if you haven't). You can do this by overriding the onConfigure method e.g. :-
#Override
public void onConfigure (SQLiteDatabase db) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
db.setForeignKeyConstraintsEnabled(true);
} else {
db.execSQL("pragma foreign_keys = ON");
}
}

SQLITE firing query to search with a non primary key value

db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" + KEY_ROWID + " INTEGER PRIMARY KEY
AUTOINCREMENT, KEY_PNAME + " TEXT NOT NULL, " + KEY_LOC + " TEXT NOT NULL, "
+ KEY_TH + " TEXT NOT NULL);"
Now suppose I have to extract the value of KEY_ROWID of a particular value of KEY_LOC.then what query should I fire on database because in my app if I have a location's latitude longtitude(KEY_LOC). I should be able to show rest of the data associated with that location.

Updating foreign key field in SQLite using ContentValues and update()

I am having trouble getting a foreign key to update in a SQLite table that's running in my Android app.
I have two tables, CASHFLOW_TABLE and ACCOUNT_TABLE. CASHFLOW_TABLE has a foreign key column that references the _id column of ACCOUNT_TABLE. I want to update values in one line of CASHFLOW_TABLE, but when I run this code
String where = "_id=?";
String[] whereArgs = {"7"};
ContentValues cv = new ContentValues();
cv.put(CF_COL_PURPOSE, "Coffee");
cv.put(CF_COL_VALUE, 2.5);
cv.put(CF_COL_ACCOUNT_ID, 4);
myDatabase.update(CF_TABLE_NAME, cv, where, whereArgs);
I receive the error message:
E/Database(22962): Error updating ACCOUNT_ID=4 VALUE=2.5 PURPOSE=Coffee using UPDATE CASHFLOW_TABLE SET ACCOUNT_ID=?, VALUE=?, PURPOSE=? WHERE _id=?
The reason I think this has something to do with the fact that CF_COL_ACCOUNT_ID is a foreign key is that when I remove
cv.put(CF_COL_ACCOUNT_ID, 4);
and run the code just to update just the other values, it works fine. Any ideas what I am doing wrong?
Update: when I try to run the update as an SQL statement, I get the following error, which does seem to suggest that the problem is with the foreign key constraint:
E/Database(24650): Failure 19 (foreign key constraint failed) on 0x314530 when executing 'update CASHFLOW_TABLE set VALUE= 2.5, PURPOSE='coffee', ACCOUNT_ID=4 where _id = 7'
Below is the code in onCreate() that sets up the tables and foreign key constraint. I have simplified it a bit here--there are other columns and one other foreign key (for a third table not shown here).
db.execSQL("Create table " + A_TABLE_NAME + " (" + A_COL_ID + " integer primary key autoincrement, " + A_COL_NAME
+ " text default ('" + A_DEFAULT_ACCOUNT + "'));");
db.execSQL("Create table " + CF_TABLE_NAME + " (" + CF_COL_ID
+ " integer primary key autoincrement, " + CF_COL_VALUE
+ " real not null, "
+ CF_COL_PURPOSE + " text not null, " + CF_COL_TIMESTAMP
+ " text not null default (strftime('%s','now')), "
+ CF_COL_ACCOUNT_ID
+ " integer not null default 1, foreign key ("
+ CF_COL_ACCOUNT_ID + ") references " + A_TABLE_NAME + " ("
+ A_COL_ID + ") on delete set default);");

Resources