SQL INSERT INTO returning autoincrement field - sql

I'm a long time desktop app C++ programmer new to SQL. I need to insert into a table with an autoincrment field, and have that sql statement return the new value for the autoincrement field.
Something LIKE:
INSERT INTO Entrys ('Name','Description')
VALUES ('abc','xyz')
SELECT Entrys.EntryID WHERE EntryID=[THE ONE JUST INSERTED!]
Sorry for being a noob.

Assuming that you're using SQL Server, you can use scope_identity to return "the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch."
INSERT INTO Entrys ('Name','Description') VALUES ('abc','xyz');
SELECT SCOPE_IDENTITY()

select scope_identity
insert into table values ('string value');select scope_identity()
Details here

In SQL Server, you can also use the OUTPUT clause on your INSERT statement:
INSERT INTO Entrys('Name', 'Description')
OUTPUT Inserted.EntryID
VALUES ('abc','xyz')
This will output the newly created IDENTITY field value.

In MySQL you can use LAST_INSERT_ID()

As #marc_s said for SQL Server, in PostgreSQL you can obtain the same behaviour with:
INSERT INTO Entrys ('Name','Description')
VALUES ('abc','xyz')
RETURNING EntryID;
RETURNING is also really useful when you're inserting several tuples and you want all the generated IDs for each of the rows.

Related

SQL Insert Query With Condition

I am trying to insert values into 1 column of a table when a condition is satisfied.
Note: The table already contains data for all the columns but for 1 which is empty. I would like to insert value into this 1 column depending on the WHERE clause.
I have this query:
INSERT INTO <TABLE_NAME>
(COLUMN_NAME)
(VALUE)
WHERE <CONDITION>
I am getting an exception:
Incorrect Syntax Near WHERE Keyword
I am able to do this using UPDATE:
UPDATE <TABLE_NAME>
SET <COL_NAME>
WHERE <CONDITION>
But was wondering why the INSERT query was failing. Any advise appreciated.
As I understand your problem, you already have data in one row, and one column in that row does not have value, so you want to add value in to that column.
This the scenario for Update existing row, not the insert new row. You have to use UPDATE clause when data already present and you want to modify record(s). Choose insert when You want to insert new row in table.
So in your current scenario, Update Clause is your friend with Where Clause as you want to modify subset of records not all.
UPDATE <TABLE_NAME>
SET <COL_NAME>
WHERE <CONDITION>
INSERT Clause does not have any Where Clause as per any RDBMS syntax(I think). Insert is condition less sql query, While SELECT, UPDATE, DELETE all are conditional commands, you can add Where Clause in all later ones.
In order to add a value into the one column when the rows are already populated, you will need to use the update statement.
If you need to insert a new row that has a where clause, you will need to use an insert into select statement:
INSERT INTO <table> (<columns>)
SELECT <columns>
FROM <table>
WHERE <condition>;
The SQL Insert dont accept where parameters, you could check this: SQL Insert Definition...
I do not know the whole question of what you want to do, but just using the INSERT statement is not possible, however it is possible to condition the insertion of data into a table, if this data is dependent on another table or comes from another table ... check here... SQL Insert explain in wikipedia
like this:
Copying rows from other tables
INSERT INTO phone_book2
SELECT *
FROM phone_book
WHERE name IN ('John Doe', 'Peter Doe')
or
INSERT INTO phone_book2 ( [name], [phoneNumber] )
SELECT [name], [phoneNumber]
FROM phone_book
WHERE name IN ('John Doe', 'Peter Doe')
Based on your question I have the feeling that you are trying to UPDATE a column in a table rather than insert.
Something like:
UPDATE column SET value WHERE different_column_value = some_value
I know this is kinda late, for those who still want to use the where clause in an insert query, it's kinda possible with a hack.
My understanding is that, you want to insert only if a condition is true. Let's assume you have a column in your database "surname" and you want to insert only if a surname doesn't exist from the table.
You kinda want something like INSERT INTO table_name blha blha blah WHERE surname!="this_surname".
The solution is to make that cell unique from your admin panel.
Insert statement will insert a new record. You cannot apply a where clause to the record that you are inserting.
The where clause can be used to update the row that you want.
update SET = where .
But insert will not have a where clause.
Hope this answers your question
INSERT syntax cannot have WHERE clause. The only time you will find INSERT has WHERE clause is when you are using INSERT INTO...SELECT statement.
I take it the code you included is simply a template to show how you structured your query. See the SO questions here, here and the MSDN question here.
In SQL Server (which uses Transact-SQL aka T-SQL) you need an UPDATE query for INSERT where columns already have values - by using the answer #HaveNoDisplayName gave :)
If you are executing INSERT / UPDATE from code (or if you need it regularly) I would strongly recommend using a stored procedure with parameters.
You could extend the procedure further by adding an INSERT block to the procedure using an IF-ELSE to determine whether to execute INSERT new record or UPDATE an existing, as seen in this SO answer.
Finally, take a look at SQLFiddle for a sandbox playground to test your SQL without risk to your RDMS :-)
Private case I found useful: Conditional insert which avoids duplications:
-- create a temporary table with desired values
SELECT 'Peter' FirstName, 'Pan' LastName
INTO #tmp
-- insert only if row doesn't exist
INSERT INTO Persons (FirstName, LastName)
SELECT *
FROM #tmp t
WHERE NOT EXISTS (SELECT * FROM Persons where FirstName=t.FirstName and LastName=t.LastName)
If the data need to be added for a column for an existing row then it’s UPDATE.
INSERT is creating a new row in the table.
For conditional INSERT, you can use the MERGE command.

How to Return the ID Value When Inserting a Record Using ElevateDB

With SQL server you can simply return ##Identity to get the ID value of the last insert.
Is there a way to do this using elevatedb?
ElevateDB provides a LASTIDENTITY function which returns the last identity value assigned to the specified column in the specified table.
SELECT LASTIDENTITY('Customer', 'CustNo') AS LastCustNo
You can also obtain the same information using the INSERT statement.
EDBQuery1.SQL.Clear;
EDBQuery1.SQL.Add('INSERT INTO Table1 (ID, Text1)');
EDBQuery1.SQL.Add('VALUES(:ID, :Text1)');
EDBQuery1.Prepare;
EDBQuery1.ParamByName('Text1').AsString:='Some text';
EDBQuery1.ExecSQL;
ShowMessage(EDBQuery1.ParamByName('ID').AsString);
INSERT statements automatically set all parameters to IN/OUT so that
any generated/computed column values (including IDENTITY columns) can
be retrieved via the same parameters after the INSERT is executed.
The above example is from the Support Forum.
ElevateDB does not support identity or auto-incrementing column types. So, there is no syntax like ##Identity.

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.

SQL Server - Return value after INSERT

I'm trying to get a the key-value back after an INSERT-statement.
Example:
I've got a table with the attributes name and id. id is a generated value.
INSERT INTO table (name) VALUES('bob');
Now I want to get the id back in the same step. How is this done?
We're using Microsoft SQL Server 2008.
No need for a separate SELECT...
INSERT INTO table (name)
OUTPUT Inserted.ID
VALUES('bob');
This works for non-IDENTITY columns (such as GUIDs) too
Use SCOPE_IDENTITY() to get the new ID value
INSERT INTO table (name) VALUES('bob');
SELECT SCOPE_IDENTITY()
http://msdn.microsoft.com/en-us/library/ms190315.aspx
INSERT INTO files (title) VALUES ('whatever');
SELECT * FROM files WHERE id = SCOPE_IDENTITY();
Is the safest bet since there is a known issue with OUTPUT Clause conflict on tables with triggers. Makes this quite unreliable as even if your table doesn't currently have any triggers - someone adding one down the line will break your application. Time Bomb sort of behaviour.
See msdn article for deeper explanation:
http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx
Entity Framework performs something similar to gbn's answer:
DECLARE #generated_keys table([Id] uniqueidentifier)
INSERT INTO Customers(FirstName)
OUTPUT inserted.CustomerID INTO #generated_keys
VALUES('bob');
SELECT t.[CustomerID]
FROM #generated_keys AS g
JOIN dbo.Customers AS t
ON g.Id = t.CustomerID
WHERE ##ROWCOUNT > 0
The output results are stored in a temporary table variable, and then selected back to the client. Have to be aware of the gotcha:
inserts can generate more than one row, so the variable can hold more than one row, so you can be returned more than one ID
I have no idea why EF would inner join the ephemeral table back to the real table (under what circumstances would the two not match).
But that's what EF does.
SQL Server 2008 or newer only. If it's 2005 then you're out of luck.
There are many ways to exit after insert
When you insert data into a table, you can use the OUTPUT clause to
return a copy of the data that’s been inserted into the table. The
OUTPUT clause takes two basic forms: OUTPUT and OUTPUT INTO. Use the
OUTPUT form if you want to return the data to the calling application.
Use the OUTPUT INTO form if you want to return the data to a table or
a table variable.
DECLARE #MyTableVar TABLE (id INT,NAME NVARCHAR(50));
INSERT INTO tableName
(
NAME,....
)OUTPUT INSERTED.id,INSERTED.Name INTO #MyTableVar
VALUES
(
'test',...
)
IDENT_CURRENT: It returns the last identity created for a particular table or view in any session.
SELECT IDENT_CURRENT('tableName') AS [IDENT_CURRENT]
SCOPE_IDENTITY: It returns the last identity from a same session and the same scope. A scope is a stored procedure/trigger etc.
SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];
##IDENTITY: It returns the last identity from the same session.
SELECT ##IDENTITY AS [##IDENTITY];
##IDENTITY Is a system function that returns the last-inserted identity value.
There are multiple ways to get the last inserted ID after insert command.
##IDENTITY : It returns the last Identity value generated on a Connection in current session, regardless of Table and the scope of statement that produced the value
SCOPE_IDENTITY(): It returns the last identity value generated by the insert statement in the current scope in the current connection regardless of the table.
IDENT_CURRENT(‘TABLENAME’) : It returns the last identity value generated on the specified table regardless of Any connection, session or scope. IDENT_CURRENT is not limited by scope and session; it is limited to a specified table.
Now it seems more difficult to decide which one will be exact match for my requirement.
I mostly prefer SCOPE_IDENTITY().
If you use select SCOPE_IDENTITY() along with TableName in insert statement, you will get the exact result as per your expectation.
Source : CodoBee
The best and most sure solution is using SCOPE_IDENTITY().
Just you have to get the scope identity after every insert and save it in a variable because you can call two insert in the same scope.
ident_current and ##identity may be they work but they are not safe scope. You can have issues in a big application
declare #duplicataId int
select #duplicataId = (SELECT SCOPE_IDENTITY())
More detail is here Microsoft docs
You can use scope_identity() to select the ID of the row you just inserted into a variable then just select whatever columns you want from that table where the id = the identity you got from scope_identity()
See here for the MSDN info http://msdn.microsoft.com/en-us/library/ms190315.aspx
Recommend to use SCOPE_IDENTITY() to get the new ID value, But NOT use "OUTPUT Inserted.ID"
If the insert statement throw exception, I except it throw it directly. But "OUTPUT Inserted.ID" will return 0, which maybe not as expected.
This is how I use OUTPUT INSERTED, when inserting to a table that uses ID as identity column in SQL Server:
'myConn is the ADO connection, RS a recordset and ID an integer
Set RS=myConn.Execute("INSERT INTO M2_VOTELIST(PRODUCER_ID,TITLE,TIMEU) OUTPUT INSERTED.ID VALUES ('Gator','Test',GETDATE())")
ID=RS(0)
You can append a select statement to your insert statement.
Integer myInt =
Insert into table1 (FName) values('Fred'); Select Scope_Identity();
This will return a value of the identity when executed scaler.
* Parameter order in the connection string is sometimes important. * The Provider parameter's location can break the recordset cursor after adding a row. We saw this behavior with the SQLOLEDB provider.
After a row is added, the row fields are not available, UNLESS the Provider is specified as the first parameter in the connection string. When the provider is anywhere in the connection string except as the first parameter, the newly inserted row fields are not available. When we moved the the Provider to the first parameter, the row fields magically appeared.
After doing an insert into a table with an identity column, you can reference ##IDENTITY to get the value:
http://msdn.microsoft.com/en-us/library/aa933167%28v=sql.80%29.aspx

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()