i've got a big problem with the android Api.
I'm trying to inset some Values in a SQL-Database and if the key already exist i want to update.
normaly with SQL it's no problem but android throws alwas an error.
my code:
"IF EXISTS (SELECT * FROM "+table+" WHERE Name='"+key+"')" +
" UPDATE "+table+" SET (Value='"+Value+"') WHERE Name='"+key+"'" +
" ELSE" +
" INSERT INTO Table1 (Name,Value) VALUES ('"+key+"','"+Value+"')";
the error i alwas get:
09-19 19:56:46.311: E/AndroidRuntime(32454): Caused by:
android.database.sqlite.SQLiteException: near "CASE": syntax error (code 1): , while compiling: CASE WHEN EXISTS (SELECT * FROM Settings WHERE Name='AppVersion')THEN UPDATE Settings SET (Value='0.5 beta') WHERE Name='AppVersion'ELSE INSERT INTO Table1 (Name,Value) VALUES ('AppVersion','0.5 beta')`
I've also tried to use "CASE" but it doesnt work neither.
"CASE WHEN EXISTS (SELECT * FROM "+table+" WHERE Name='"+key+"')" +
"THEN UPDATE "+table+" SET (Value='"+Value+"') WHERE Name='"+key+"'" +
"ELSE INSERT INTO Table1 (Name,Value) VALUES ('"+key+"','"+Value+"')";
Please can anybody tell me how it works.
PS.: sorry for bad english.
SQLite (obviously) does not support the syntax that you are trying to use.
There are basically two options:
Use SQLite's "ON CONFLICT REPLACE" syntax with an INSERT statement
this requires a unique constraint (in this case, on the 'Name' column).
be aware that this will first delete the old row, and then insert a new one.
If delete/insert is unacceptable to you, then you'll probably have to resort to attempting to update first, get the update count, and if it's zero, do the insert.
Related
I am trying to create a static list of timestamps so that i can join them agains another table to create chart data. So far I have a query in this format SELECT * FROM (VALUES('a'),('b'),('c'),('d')) AS tbl ,which is working in sqlitestudio but not in android 4.4. When I run the query in the phone I get the error
android.database.sqlite.SQLiteException: near "VALUES": syntax error (code 1): , while compiling: SELECT * ...
I have also tried wrapping the values term inside another select like this SELECT * FROM (SELECT * FROM (VALUES('a'),('b'),('c'),('d'))) AS tbl but I still get the same error.
The full query now looks like this
SELECT * FROM (select * from ( VALUES (1458111312025),
(1455667200000),
(1455753600000),
(1455840000000),
(1455926400000),
(1456012800000),
(1456099200000),
(1456185600000),
(1456272000000),
(1456358400000),
(1456444800000),
(1456531200000),
(1456617600000),
(1456704000000),
(1456790400000),
(1456876800000),
(1456963200000),
(1457049600000),
(1457136000000),
(1457222400000),
(1457308800000),
(1457395200000),
(1457481600000),
(1457568000000),
(1457654400000),
(1457740800000),
(1457827200000),
(1457913600000),
(1458000000000),
(1458086400000))) i LEFT JOIN (
SELECT (osysdate- (osysdate % 86400000) ) interval, SUM(field004) totalval FROM onlineactivities WHERE field003 !=300000 and osysdate> 1455605711999 GROUP BY interval )
onl ON i.'' = onl.interval;;
Note that this works in sqlitestudio with sqlite version 3.8.10 but not in android kitkat (not sure about the sqlite version in it) What could be the problem?
Also please check out this question which is what I am trying to do but with sqlite and this answer
The VALUES syntax is available since SQLite 3.8.3, which is not available in every Android version.
To be compatible with earlier SQLite versions, you have to use a compound query:
SELECT 1458111312025 UNION ALL
SELECT 1455667200000 UNION ALL
...
Alternatively, put all the values into a temporary table.
with a simple query, using bindargs works fine, but as soon as I include select case ..... in the query it always fails "Can't pass bindargs for this sql", if I test with all the '?'s replaced with fixed values, it compiles and runs OK, so it does seem to be that argument binding cannot cope with selects embedded inside select case. Is this true?
the query I am compiling is:
(SELECT CASE
WHEN ((SELECT _id FROM point2D WHERE x=? AND y=?) IS NULL ) THEN 0
ELSE (SELECT _id FROM point2D WHERE x=? AND y=? LIMIT 1))
and the table is setup with
create table if not exists point2D ( _id INTEGER PRIMARY KEY AUTOINCREMENT,
x REAL, y REAL )
I only want a single compiled query that returns the key to an existing matching record, or a known 'its not there' value, but of course a simple query like
SELECT _id FROM point2D WHERE x=? AND y=? LIMIT 1
will cause an exception with simpleQueryForLong when there is nothing found (which is quite expensive in cpu time)
I cannot use insert or update, because update actually replaces the old row with a new row (and hence a new _id) which screws up all the other stuff pointing to this.
You have kept the actual parameter code a secret, but I'd guess that you provide only two parameters although the query has four.
You can use one parameter multiple times if you give it a name or a number:
(SELECT CASE
WHEN ((SELECT _id FROM point2D WHERE x=?1 AND y=?2) IS NULL ) THEN 0
ELSE (SELECT _id FROM point2D WHERE x=?1 AND y=?2 LIMIT 1))
However, for this particular query, you'd better use the ifnull function:
(SELECT ifnull((SELECT _id FROM point2D WHERE x=? AND y=?), 0))
(And I doubt that the outer subquery is actually needed.)
I got sqlite DB on my android app to save reservations.
The one of the tables there contains the header of each reservation that may contain several parts of the reservation, each reservation has RES_ID while each part has PART_ID
the main table contains only the RES_ID as primary key, i have other tables that contains the parts in each of them PART_ID and RES_ID are both primary keys
i have a case in which i insert several part objects into the DB so eventually what happens is i try to insert a two or more rows with the same RES_ID to the table.
naturally i get SQLiteException, constrains violation since there's already a row with that primary key.
Is there an SQL statement or a java method\const that will notify SQLite that failing is ok and i don
't want the exception ? (just for that table)
Shouldn't this work :
INSERT ((SELECT v1 AS c1, v2 AS c2, ... , vn AS cn) EXCEPT tablename) INTO tablename;
?
Or similar :
INSERT ((SELECT v1 AS c1, v2 AS c2, ... , vn AS cn) WHERE NOT EXISTS (SELECT * FROM tablename WHERE pkc1 = pkv1 AND pkc2 = pkv2 AND ... AND pkcj =pkvj)) INTO tablename;
?
When I get your question right, you are looking for insert or replace. Click
replace is a shortcut for this.
There might be another way but indeed using replace instead of INSERT would do the job nicely.
Checking with the sqlite3 console client i was able to insert a non existing row into the talked about table. If the row already exists, the values will be updated anyway.
10x Jeff and janoliver!
I have a common problem, and have looked at several solutions but haven't seen one that fits this case.
I have a temporary table that is defined as follows:
public static final String GROUP_TABLE_CREATE =
"CREATE TEMP TABLE "+GROUP_TABLE_NAME+" ("
+GROUP_ID_COLUMN_NAME+" INTEGER PRIMARY KEY AUTOINCREMENT, "
+GROUP_GROUP_ID_COLUMN_NAME+" INTEGER NOT NULL UNIQUE, "
+GROUP_COLUMN_NAME+" VARCHAR(64) NOT NULL)";
The table is created without any problems. I then download some data to insert into it and use the following query to insert it:
ContentValues contentValues = new ContentValues();
contentValues.put(WhereWolfOpenHelper.GROUP_GROUP_ID_COLUMN_NAME, groupID);
contentValues.put(WhereWolfOpenHelper.GROUP_COLUMN_NAME, groupName);
db.insert(WhereWolfOpenHelper.GROUP_TABLE_NAME, null, contentValues);
And then I get the following error:
08-05 08:52:37.791: ERROR/Database(847): Error inserting group_name=Friends group_id=2
08-05 08:52:37.791: ERROR/Database(847): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
The error appears twice, and the only data in the database is the group named Friends (there should be two more entries).
I have another table with very similar code that works without any problems, so I'm guessing it's just some silly mistake that I haven't spotted. Anyone got any ideas?
If "constraint failed" than something in table scheme should tell us what is wrong.
I see what it show data what it want to insert, this means what NOT NULL constraint is OK.
In this case I've only one assumption what you already inserted some GROUP_GROUP_ID_COLUMN_NAME with value 2 and UNIQUE constraint is failed because of that.
Are you using a temporary table on purpose? A temporary table dies once the DB connection is closed. If this is the case, the table will get created and the insert will not correspond to any table. So the constraint 19 can correspond to 'Table not found'
You shouldn't pass null values in insert method. Pass empty strings.
I want to force a foreign key constarint on a table in an Android application.
I've searched that this can be done by using triggers:
I did it like this:
db.execSQL("CREATE TRIGGER dept_id_trigger22+" +
" AFTER INSERT "+
" OF EmployeeName ON Employees"+
" BEGIN"+
//Condition
" RAISE(ABORT,'error') END;");
but no error was raised and the illegal values are inserted.
what is wrong with this ?
Ok I got it
Android supports SQLite triggers.
The correct syntax is
db.execSQL("CREATE TRIGGER dept_id_trigger22" +
" AFTER INSERT "+
"ON Employees"+
" BEGIN"+
//Condition
" SELECT RAISE(ABORT,'error'); END;");
I forgot to add semicolon after the raise statement.
This does not execute the statement but it does not throw an exception.
still will search for how to throw exceptions
thanks
Foreign keys are only supported on Android on Froyo (2.2) or newer, for previous versions you can include them but SQLite ignores them. All Android versions of SQLite support triggers to produce the same effect though.
Newer versions of SQLite (for your PC) has a command called "genfkey" that will analyze your SQLite database (which has foreign keys in it) and produce the equivalent triggers. This way you can design your tables with foreign key constraints while also supporting all versions of the OS.
On Windows, open the SQLite command line tool with your database file as a parameter:
sqlite3 mydatabase.db
.genfkey --exec
This will generate triggers for all of your key constraints.
I don't expect any votes for this answer, just to let you know:
You could use another database, for example the H2 database. Disclaimer: I'm the main author of H2.
There are some disadvantages: some (not all) operations are slower, for example opening and closing a database. The jar file is relatively big (about 1 MB). You would have to use the JDBC API.
But the advantage is: H2 supports using triggers, constraints, and so on.
To delete Last 50 rows when count is greater than 100
sqliteDB.execSQL("CREATE TRIGGER IF NOT EXISTS delete_trigger
AFTER INSERT ON table1
WHEN (SELECT COUNT(*) FROM table1) > 50 " +
BEGIN
delete From table1 where id not in(select id from table1 order by id desc limit 100;
END;"
);
I discovered that the SQLite version used does not support foreign keys - so I expect that triggers are not supported, too.