I have a (key,value) database table in sqlite. I want to update an existing key with the value in case it already exists. And if the key doesn't exist, insert the key and value into the table.
What would be best sql statement to do that?
I am creating the table using the statement:
CREATE TABLE KeyValueTable ( EntityName TEXT PRIMARY KEY NOT NULL, EntityValue BLOB)
https://www.sqlite.org/lang_UPSERT.html provides the information about how to do upsert in sqlite. Note that this feature was added to SQLite with version 3.24.0 (2018-06-04)
INSERT OR REPLACE INTO KeyValueTable VALUES ($key, $value)
While INSERT OR REPLACE is not, in general, equivalent to an UPSERT, it should work for your situation, and is compatible with older versions of SQLite.
Related
Very simple source->target insert, source records are treated as "Insert", target transformation uses the "Insert" function only. Target Teradata table is a set with a primary index defined. Informatica target trans also has a primary key defined. Teradata informatica relational connection does not have a "bulk" option.
So how come Informatica does create a duplicate record, while even a direct insert into Teradata can not.
Any ideas?
I have a Xamarin.Forms app that uses a SQLite database locally on the device. Here's some sample data structure:
Table x: id, name
Table y: id, name
Table x_y: id, x_id, y_id
Since SQLite doesn't support altering columns, one of the schema updates we sent down in a patch did the following:
Rename table x to x_temp
Create new/updated table x
Insert all data from table x_temp into table x
Drop table if exists x
That seems to work just fine. However, when I'm attempting to run an insert statement on table x_y, I am getting a SQLite exception: "no such table: main.x_temp".
When I look at the SQLite query string while debugging there is no mention of table x_temp whatsoever. So, if I delete the entire database and re-create everything the insert works just fine.
I'm from a MSSQL background, am I not understanding something about SQLite in general? Is the foreign key constraint from table x_y trying to reference x_temp because I renamed the original table (I may have just answered my own question)? If that's the case, surely there is a way around this without having to cascade and re-create every table?
Any input would be appreciated. Thanks!
I believe that your issue may be related to the SQlite version in conjunction with whether or not Foreign Key Support has been turned on.
That is the likliehood is that :-
Is the foreign key constraint from table x_y trying to reference
x_temp because I renamed the original table (I may have just answered
my own question)?
Would be the issue, as you likely have Foreign Key Support turned on as per :-
Prior to version 3.26.0 (2018-12-01), FOREIGN KEY references to a table that is renamed were only edited if the PRAGMA foreign_keys=ON, or in other words if foreign key constraints were begin enforced.
With PRAGMA foreign_keys=OFF, FOREIGN KEY constraints would not be changed when the table that the foreign key referred to (the "parent table") was renamed.
Beginning with version 3.26.0, FOREIGN KEY constraints are always converted when a table is renamed, unless the PRAGMA legacy_alter_table=ON setting is engaged. The following table summaries the difference:
SQL As Understood By SQLite - ALTER TABLE
If that's the case, surely there is a way around this without having
to cascade and re-create every table?
Yes, as the latest version of SQlite on Android is 3.19.0 (I believe), then you can turn Foreign Key support off using the foreign_keys pragma when renaming the table.
Note Foreign Keys cannot be turned off within a transaction.
See SQL As Understood By SQLite - ALTER TABLE and PRAGMA foreign_keys = boolean;
Is it possible to add an ON DELETE CASCADE to a table after it has been created?
My schema is as follows:
CREATE TABLE skills(name varchar, skill varchar, level int, foreign key(name) references runners(name), primary key(name, skill));
And I would like to cascade if the foreign key is deleted.
SQLite's ALTER TABLE command cannot do what you want.
However, it is possible to bypass the SQL interpreter and change the internal table definition directly.
SQLite stores table definitions as a textual copy of the CREATE TABLE command in its sqlite_master table; check out the result of this query:
SELECT sql FROM sqlite_master WHERE type='table' AND name='skills';
Add your cascade specification to that string, then enable write access to sqlite_master with PRAGMA writable_schema=1; and write your new table definition into it:
UPDATE sqlite_master SET sql='...' WHERE type='table' AND name='skills';
Then reopen the database.
WARNING: This works only for changes that do not change the on-disk format of the table. If you do make any change that changes the record format (such as adding/removing fields, or modifying the rowid), your database will blow up horribly.
Is it possible to add an ON DELETE CASCADE to a table after it has been created?
My schema is as follows:
CREATE TABLE skills(name varchar, skill varchar, level int, foreign key(name) references runners(name), primary key(name, skill));
And I would like to cascade if the foreign key is deleted.
SQLite's ALTER TABLE command cannot do what you want.
However, it is possible to bypass the SQL interpreter and change the internal table definition directly.
SQLite stores table definitions as a textual copy of the CREATE TABLE command in its sqlite_master table; check out the result of this query:
SELECT sql FROM sqlite_master WHERE type='table' AND name='skills';
Add your cascade specification to that string, then enable write access to sqlite_master with PRAGMA writable_schema=1; and write your new table definition into it:
UPDATE sqlite_master SET sql='...' WHERE type='table' AND name='skills';
Then reopen the database.
WARNING: This works only for changes that do not change the on-disk format of the table. If you do make any change that changes the record format (such as adding/removing fields, or modifying the rowid), your database will blow up horribly.
I set up a SQLite Database DB Connection via the CF Admin after installing the JDBC Driver. After setting it up I got a successful connection message. I also know that I connected successfully because if I run a simple select query it doesn't fail out and if I run a CFDump it shows the proper columns. To further test this simple select statement, if I changed the table name it does fail. So, it's not a connection issue.
I am simply trying to insert records into a table and then check to see if those records were added. These are the queries I am using:
<cfquery datasource="fooDB" name="foo">
INSERT INTO FooTable
(FooColumn)
VALUES
('Test')
</cfquery>
<cfquery datasource="fooDB" name="checkIfwasSuccessful">
SELECT *
FROM FooTable
</cfquery>
This is my SQlite table creator:
CREATE TABLE FooTable (
id INTEGER PRIMARY KEY,
FooColumn TEXT,
OtherColumn1 TEXT,
OtherCOlumn2 TEXT
);
The CFDump of the query checkIfwasSuccessful is an empty result.
Any ideas??
Thank you in advance!!
Use Cftransaction to verify that your query is being commmited.
Have you tried either a) supplying an id with the insert, or b) using the AUTOINCREMENT keyword after PRIMARY KEY?