SQLite insert or select primary key - sql

I want to insert a row if it doesn't already exist. If it does already exist, I want to get it's primary key.
Can this be done without using two queries, for instance using a UNIQUE constraint on the columns and ON CONFLICT ... TELL ME THE CONFLICTING ROWID?

Please note that I don't have experience with SQLite. However, after perusing the online documentation, I don't believe that it supports data-change table references, so no, this isn't possible.
My reccommendation is to write your INSERT in such a way that it won't fail if the row exists - it just won't insert a row. Something like this:
INSERT INTO destinationTable (colA, colB)
(SELECT :colAValue, :colBValue
WHERE NOT EXISTS (SELECT '1'
FROM destinationTable
WHERE uniqueColumn = :uniqueColumn))
This works because the selection won't return a row if it already exists. You can then either look at the return code/state to see if it INSERTed a row, or just SELECT with the unique column, to get the identity column.
DON'T rely on your constraint to catch this. Constraints are to catch application errors, and this is solely a business/implementation detail.

In a word, no. You can't, with SQLite, either INSERT data or, on some condition, SELECT it.
Other SQL engines might allow it, but SQLite can't.
What you can do is INSERT OR IGNORE, which will just not bring up an error. See http://sqlite.org/lang_conflict.html

Related

SQL Statement Error table to table

Trying insert table data into another table,
But I'm getting the following error:
Msg 2627, Level 14, State 1, Line 4
Violation of PRIMARY KEY constraint 'PK___4__10'. Cannot insert duplicate key in object 'dbo.tbl_Diagnosis_Table'.
Appears to be a duplicate primary key between both tables. Both tables have the same fields and data types, different data. What query can resolve this issue?
INSERT INTO tbl_Diagnosis_Table
SELECT *
FROM tbl_Holding_Diagnosis_Table
INSERT INTO tbl_Diagnosis_Table(Code, [Description], Comments, Discontinued)
(SELECT
Code, [Description], Comments, Discontinued
FROM
tbl_Holding_Diagnosis_Table);
Assuming Code is the primary key this should eliminate the duplicate rows from the insert:
INSERT INTO tbl_Diagnosis_Table (Code, [Description], Comments, Discontinued)
SELECT Code, [Description], Comments, Discontinued
FROM tbl_Holding_Diagnosis_Table
WHERE tbl_Holding_Diagnosis_Table.Code NOT IN
(SELECT Code FROM tbl_Diagnosis_Table)
If the primary key is some other column, or a composite key, you might need to use a join instead.
You might want to look at the MERGE statement if you want to update existing rows and only insert new.
You need a WHERE with an IN Clause To filter the records to insert, but first you need to know wich fields form the primary key.
If what you're saying is correct i.e. all the values are unique, it leaves only one option. Make sure that if there is an identity column in table tbl_diagnosis_table, you are setting the IDENTITY_INSERT to ON on this table and providing values manually in the select. It might have been possible that the seed and increment was reset in the past. In case you were wrong, you have to use a where clause as suggested by others.
I was going to suggest using a Merge query to do insert or update until I noticed the two inserts in the sample code both do the same insert. The error also says the error is on line 4 which is where the second insert occurs. If the two inserts aren't two examples of the problematic code, then the resolution may be as simple as removing one of the inserts.
Otherwise the other answers are correct, the duplicate rows need to be filtered and the IDENTITY_INSERT has to be turned on for the table.
SET IDENTITY_INSERT tbl_Diagnosis_Table ON -- if it is necessary to have the same primary key
MERGE tbl_Diagnosis_Table AS target
USING (SELECT Code, Description, Comments, Discontinued FROM tbl_Holding_Diagnosis_Table) AS source (Code, Description, Comments, Discontinued)
ON (target.Code = source.Code)
WHEN MATCHED THEN
UPDATE SET Description = source.Description,
Comments = source.Comments,
Discontinued = source.Discontinued
WHEN NOT MATCHED THEN
INSERT (Code, Description, Comments, Discontinued)
VALUES (source.Code, source.Description, source.Comments, source.Discontinued)
END; -- missing semicolons causes errors
SET IDENTITY_INSERT tbl_Diagnosis_Table OFF
Do your homework though. There are some very good reasons not to use Merge.
Use Caution with SQL Server's MERGE Statement
Indexed views and Merge
Optimizing Merge Statement Performance

Insert into ignore duplicates that are not the primary key

I'm trying to find a query for sql that will just insert values but not do it should the value exist. Now ive seen alot of examples but they all rely on primary keys or table to table moves. I just want to add a new row in the table and assuming that one of the collumns doesnt have the same value add it. I know the following wont work but its as close to I think it would be and might just clear it up if my writting is not enough.
INSERT INTO table (txtLastName,txtEmail,txtZip)
Values ('Tester','test#test.com','12345')
WHERE txtLastName <> 'Tester'
or WHERE txtEmail <> 'test#test.com'
or WHERE txtZip <> '12345'
Using MS SQL Server.
You should create a Unique Constraint composed by the three fields (txtLastName, txtEmail, txtZip).
The links directs you to SQL Server docs, but the concept of unique constraint is RDBMS universal.
Just beware that when you create a Unique Constraint, your duplicate insert will not just fail silently: it will throw an error saying the insert tried to violate the unique constraint. And, of course, it should do that! Make sure your code handles that exception.
Try this:
INSERT INTO table (txtLastName,txtEmail,txtZip)
SELECT 'Tester','test#test.com','12345'
WHERE NOT EXISTS (SELECT *
FROM table
WHERE txtLastName = 'Tester'
AND txtEmail = 'test#test.com'
AND txtZip = '12345'
)

SQL - Inserting a row and returning primary key

I have inserted a row with some data in a table where a primary key is present. How would one "SELECT" the primary key of the row one just inserted?
I should have been more specific and mentioned that I'm currently
using SQLite.
For MS SQL Server:
SCOPE_IDENTITY() will return you the last generated identity value within your current scope:
SELECT SCOPE_IDENTITY() AS NewID
For SQL Server 2005 and up, and regardless of what type your primary key is, you could always use the OUTPUT clause to return the values inserted:
INSERT INTO dbo.YourTable(col1, col2, ...., colN)
OUTPUT Inserted.PrimaryKey
VALUES(val1, val2, ....., valN)
SQL Server:
You can use ##IDENTITY. After an insert statement, you can run:
select ##identity
This will give you the primary key of the record you just inserted. If you are planning to use it later, I suggest saving it:
set #MyIdentity = ##identity
If you are using this in a stored procedure and want to access it back in your application, make sure to have nocount off.
For MySQL, use LAST_INSERT_ID()
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
You should also be able to start a transaction, insert the row, and select the row using some field that has a unique value that you just inserted, like a timestamp or guid. This should work in pretty much any RDBMS that supports transactions, as long as you have a good unique field to select the row with.
If you need to retrieve the new index in MS SQL when there are triggers on the table then you have to use a little workaround. A simple OUTPUT will not work. You have to do something like this (in VB.NET):
DECLARE #newKeyTbl TABLE (newKey INT);
INSERT INTO myDbName(myFieldName) OUTPUT INSERTED.myKeyName INTO #newKeyTbl VALUES('myValue'); " & _
SELECT newKey FROM #newKeyTbl;"
If using .NET, then the return value from this query can be directly cast to an integer (you have to call "ExecuteScalar" on the .NET SqlCommand to get the return).
For SQLite:
SELECT [Column_1], [Column_2],... [Column_n]
FROM [YourTable]
WHERE rowid = (SELECT last_insert_rowid())
whereas:
Column_1, Column_2,... Column_n: are the primary key of YourTable.
If you'd created YourTable with primary key replaced rowid (i.e. one column pk defined as INTEGER PRIMARY KEY) you just use:
SELECT last_insert_rowid()
Which is a common case.
Finally, this wont work for WITHOUT_ROWID tables.
Please Check:
https://www.sqlite.org/lang_corefunc.html#last_insert_rowid
For PostgreSQL,
INSERT INTO tablename (col1, col2, ...)
VALUES (val1, val2, ...)
RETURNING idcol;
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted (or updated, if an ON CONFLICT DO UPDATE clause was used). This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number. However, any expression using the table's columns is allowed.
https://www.postgresql.org/docs/current/sql-insert.html
For Postgresql:
SELECT CURRVAL(pg_get_serial_sequence('schema.table','id'))
Source: PostgreSQL function for last inserted ID
select MAX(id_column) from table
That, in theory, should return you that last inserted id. If it's a busy database with many inserts going on it may not get the one you just did but another.
Anyhow, an alternative to other methods.

Insert ...on duplicate in oracle?

I am new to Oracle and I want to check if particular primary key value is present or not. If value exists then just update the entire row .If value is not present, then insert new row.
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
Code above works on MySql. How to achieve the same in Oracle 10g? Can anyone please help?
Look up the SQL standard MERGE statement, which is supported by (more recent versions of) Oracle. This will work with other DBMS than Oracle too.

SQL: is it possible to combine an INSERT and SELECT statement into one

I want to add a row using SQLs INSERT statement. Is it possible that as part of this statement I can somehow get the value of the column userId which I don't update but is the AUTO_INCREMENT primary key. I need this value to update another table, however I can't follow the Insert statement immediately with a SELECT statement as there is no other unique identifier in the table on which to select.
INSERT INTO objectUrl(disp_name, loggedIn) VALUES('please change this', true)
Is it possible to get the row number (column name userId) and if so how do you do it?
In MySQL it's called LAST_INSERT_ID(). I believe to be technically correct, the two statements should be wrapped in a transaction so that some other INSERT doesn't mess up what ID you get back.
In SQL Sever you have IDENT_CURRENT(‘tablename’) which will only grab it from that table (still need a transaction to be safe). You could also use SCOPE_IDENTITY() which theoretically will always return the one you expect as long as you aren't doing something weird with your connection.
For MySQL you have:
select last_insert_id()