SQLite "INSERT OR REPLACE INTO" not working - sqlite

I have to write a query in sqlite to update the record if it exists or insert it if the record do not already exists. I have looked the syntax of INSERT OR REPLACE INTO from here. But in my case, when I execute the query below many times the record is duplicated. i.e If I execute the query 5 times the record is inserted 5 times.
INSERT OR REPLACE INTO NICKS
(id_nick,name_nick,date_creation)
VALUES
('nabeelarif', 'Muhammad Nabeel','2012-03-04')
Have you any idea what I am doing wrong. I am working on android platform and using 'Firefox Sqlite Manager' to test my query.

You need to have a unique index on one or a combination of those columns.
CREATE UNIQUE INDEX idx_something ON NICKS (id_nick, name_nick, date_creation);

In Android, you should use SQLiteDatabase.replace(), which does insert or update. With the Android SQLite implementation, you normally don't use raw queries represented as strings. See http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#replace%28java.lang.String,%20java.lang.String,%20android.content.ContentValues%29

Do you have a primary key or unique index defined for your table? I believe the attributes that make up the primary key or a unique index are used to determine if a row already exists or not.

Related

How to get the id of a newly-created value with Diesel and SQLite?

Diesel's SqliteBackend does not implement the SupportsReturningClause trait, so the get_result method cannot be used to retrieve a newly created value.
Is there another way to find out the id of the inserted row? Python has a solution for this. The only solution I've found so far is to use a UUID for ids instead of an autoincrement field.
The underlying issue here is that SQLite does not support SQL RETURNING clauses which would allow you to return the auto generated id as part of your insert statement.
As the OP only provided a general question I cannot show examples how to implement that using diesel.
There are several ways to workaround this issue. All of them require that you execute a second query.
Order by id and select just the largest id. That's the most direct solution. It shows directly the issues with doing a second query, as there can be a racing insert at any point in time, so that you can get back the wrong id (at least if you don't use transactions).
Use the last_insert_rowid() SQL function to receive the row id of the last inserted column. If not configured otherwise those row id matches your autoincrement primary integer key. On diesel side you can use no_arg_sql_function!() to define the underlying sql function in your crate.

SQLite batch update of a column in a table

I am using SQLite and have the following SQL Statement which updates column active with true for just row 28.
update "customer" set "active"='true' where rowid=28
What I would like to do is batch update the entire customer table, active column to true. I would have thought a loop was the best method, but I don't think sqlite supports loops. Anyone advise me how I can update a column in a table so all the records contain the value the in them?
Thanks
update "customer" set "active"='true'
will do the job (just don't specify a where)

Indexes with custom collations in sqlite

Assuming I have a schema like this:
CREATE TABLE abc(
id INTEGER PRIMARY KEY AUTOINCREMENT,
txt TEXT
);
CREATE INDEX "txtCS" ON "abc"("txt" COLLATE MY_CUSTOM_SORT);
when will sqlite use my index on txt ?
because I ran:
EXPLAIN QUERY PLAN SELECT * FROM abc ORDER BY txt COLLATE MY_CUSTOM_SORT DESC ...
and it tells me that it scans the table, twice, using the txtCS index (It doesn't search like I expected.)
MY_CUSTOM_SORT is my own sorting function that I hooked with sqliteCreateCollation. I just need that index for some queries that involve special ordering and I want them to be fast
In the EXPLAIN QUERY PLAN output, SEARCH means that the database tries to look up some particular record(s) with specific values, while SCAN means that the database goes through the entire table.
This query returns all records, so the most efficient operation is a SCAN.
Either operation can be sped up with an index.
(In a SCAN, the database just goes through all index entries in order.)

SQLite - How to insert to table with preliminary scan of the fields?

I use a database in my project and when i insert values ​​into a table i need to check if the field already has a value that does not produce an insert.
for exemple:
INSERT INTO myTable (column1) values ('some_value1')
if some_value1 alredy exists in column1 do not insert the value.
Put a unique constraint on myTable.column1. Then, whenever you try to insert a duplicate value, it won't let you as it violates the constraint. You can either catch and handle this error, or just let the DB engine do it's thing automatically.
EDIT: Note that SQLite doesn't allow you to do many alterations to your table, once it's created; so you may have to recreate your table with the constraint in place.
I believe this can be handled using the conflict resolution IGNORE method on SQLite. The code below should do the trick. The column1 here should be set to unique for this.
INSERT OR IGNORE INTO myTable (column1) values ('some_value1')
I'm using the following links for reference;
http://www.sqlite.org/lang_insert.html
http://www.sqlite.org/lang_conflict.html

SQLite Query to Insert a record If not exists

I want to insert a record into a sqlite table if its actually not inserted.
Let's say it has three fields pk, name, address
I want to INSERT new record with name if that name not added preveously.
Can we do with this in a single Query. Seems like its slightly different from SQL Queries sometimes.
Yes, you can do that with a single query.
INSERT ON CONFLICT IGNORE should help you: http://www.sqlite.org/lang_conflict.html
Put a unique key on the name, this will create a conflict when you try inserting a record if the name already exists.
The default is ABORT, so without the IGNORE, the statement will return an error. If you don't want that, use IGNORE.
If you can't make use of a UNIQUE INDEX in combination with INSERT INTO or INSERT OR IGNORE INTO, you could write a query like this;
INSERT INTO table (column)
SELECT value
WHERE NOT EXISTS (SELECT 1
FROM table
WHERE column = value)

Resources