SCOPE_IDENTITY for multiple records - sql

The below query inserts many records in a transaction. I want to fetch the newly created incremental identifier and use it in next INSERT statement
For a single record I can use like below
SELECT #new_emp_id= SCOPE_IDENTITY()
What about SCOPE_IDENTITY for multiple records? Or we can insert it into temp table and loop through it?
INSERT EmployeeBenifits(EmployeeId,BenifitID,StartdateTime,EndDateTime)
SELECT #new_emp_id,BenifitID,GetDate(),#PassedEndDate FROM Benifits
INSERT EmployeeBenifitDetails(EmpBenId,Desc)
SELECT EmpBenId,'Created Details' FROM #NewlyInsertedEmplBenifits

You should have a look at the OUTPUT clause:
INSERT INTO dbo.EmployeeBenefits(EmployeeId, BenefitID, StartdateTime, EndDateTime)
OUTPUT Inserted.EmployeeBenefitId, Inserted.EmployeeID, Inserted.BenefitID -- or whatever you want to return here
SELECT
#new_emp_id, BenefitID, GetDate(), #PassedEndDate
FROM
dbo.Benefits
Basically, the OUTPUT clause can return a result set of columns for each row that has been inserted (also works with the DELETE and UPDATE statements).
See MSDN documentation for more details
You can also send the OUTPUT rows to a temporary table (or table variable) to be further processed later on.

Related

Bulk Insert with Table Valued Parameter not working

Need to insert multiple records into a SQL table. If there are duplicates (already inserted records) then I want to ignore them. For sending multiple records from my code to SQL, I am using table valued parameter.
Below is the query. It works during the first insertion when there are no rows in the table. On subsequent insert, no rows are added.
#tvpNewFMdata is the table valued parameter.
INSERT INTO
[dbo].[FMData]
(
[Id],
[Name],
[Path],
[CreatedDate],
[ModifiedDate]
)
SELECT
fm.Id, fm.Name, fm.Path, GETUTCDATE(), GETUTCDATE()
FROM
#tvpNewFMdata AS fm
WHERE
NOT EXISTS
(
SELECT
tbl.[Id]
FROM
[dbo].[FMdata] AS tbl
WHERE
tbl.Id = fm.Id
)
I am unable to locate as to what the cause that the first time insertion works but not the second time.
Tried with even removing the WHERE NOT EXISTS clause and it was only working in the first insertion. Subsequent insertion is not adding any rows to the table.
Is there an error, or just no rows inserted? If there are just no rows being inserted, even with the removed where clause, it sounds like you might be having problems populating the table value param. Have you watched what you are sending into SQL via a breakpoint or SQL Server Profiler?
Instead of where exists, have you tried a left join to fmData, and only inserting where the fmData row is null?
I agree with Damien, this is not bulk insert.
Sorry. My apologies. It was a mistake in my code. There was no issue in the SPROC. I was parameterizing the function and was passing the wrong table valued parameter.

Trigger: How does the inserted table work? How to access its rows?

I have the following table
Data --Table name
ID -- Identity column
PCode -- Postal Code
I created the following trigger:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * from inserted
END
And inserted the following values
INSERT INTO Data VALUES (125)
INSERT INTO Data VALUES (126)
INSERT INTO Data VALUES (127)
It shows this:
But I was expecting something like this:
After the 1st insertion, the trigger is executed -> one row is shown in the inserted table.
After the 2nd insertion, the trigger is executed -> two rows are shown in the inserted table.
After the 3rd insertion, the trigger is executed -> three rows are shown in the inserted table.
According to msdn.microsoft all the rows inserted are in this table.
How can I access the inserted table so that I can see all the expected rows and not separately?
You can not. From the Use the inserted and deleted Tables article on microsoft.com, you can read:
The inserted table stores copies of the affected rows during INSERT and UPDATE statements.
That means that the inserted table will only contain rows for the current INSERT or UPDATE statement.
If you do want to see all rows for several such INSERT or UPDATE statements, you will have to store these rows in a table you created yourself.
There are 2 table available in a trigger, the inserted and the deleted. Each update on table XXX is actually a delete row X from XXX then an insert of row X in table XXX. So the inserted inside the trigger is a copy of what got inserted. You can do a lot with a trigger, but triggers are dangerous.
For example, on a performance gig, I found a huge SP being run by a trigger, we dropped it and the database came back online. Or another example, if you do a trigger wrong to audit logins, you can down the server.
As TT mentioned, if you want to see all the inserted records then you need to change your Trigger to something like this:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * into "tablename"
from
(Select * from inserted) Ins
END

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 get last inserted row from a table?

I tried below query but results in more than one row and [SCOPE_IDENTITY] as NULL.What are the alternates?
SELECT TOP 1000
[RTID],xxx,xxx
FROM [RouteTiming]
GO
SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];
GO
SELECT ##IDENTITY AS [##IDENTITY];
GO
Depending on the server version (SQL Server 2005+) you can use the OUTPUT clause:
INSERT INTO tablename (column names)
OUTPUT --this is where you put your select statement to get returned IDs etc.
VALUES (values in here, or you can use a select statememt as per usual)
MSDN Article: OUTPUT Clause (Transact-SQL)
If you are inside a stored procedure or a function, you can use INSERTED table (there is also a DELETED table) which is stored in memory until the scope is completed.
Once you have performed your insert, you can join the inserted table just like any other as long as it is within the same scope. I believe the inserted table has been around since SQL Server 2000, but it is definitely in 2005+.
MSDN Examples: Use the inserted and deleted Tables

Multiple row insert into two tables avoiding loops

I have a set of value which have to be inserted into two tables.Input has say 5 row and I have to insert these 5 rows into table A first.Table A has a identity column.Next i have to insert these 5 rows into table B with an extra column which is the identity from table A.
How this can be done with out using any loops?
Any help will be highly helpful.
INSERT INTO TABLE_A(COL2,COL3)
SELECT COL2,COL3 FROM #TEMP_TAB
set #identityval=##identity
INSERT INTO TABLE_B(COLA,COLB,COLC)
SELECT #identityval,COL2,COL3,COL4 FROM #TEMP_TAB
You cannot insert into multiple tables using a single statment.
What you could do is create an insert trigger on Table A so that after the insert occurs this performs the new insert with the identity of the value inserted into Table A and insert it into Table B.
Here is one solution.
take max of identity column from table TABLE_A
insert new records in table TABLE_A
then insert records on TABLE_B from TABLE_A with Identity greater than last max identity.
Thanks,
Gopal
What you want to do is not possible.
You can get only the value from the last insert using the ##identity variable. This way its possible to add to multiple tables setting the right foreign key without selecting the just inserted row again using a cursor. This approach is not useful when inserting multiple rows at once.
From the documentation:
Use the ##identity global variable to retrieve the last value inserted into an IDENTITY column. The value of ##identity changes each time an insert or select into attempts to insert a row into a table.
Here is a procedure which inserts a single row and you can use the return value to create a reference to the inserted data in another table:
create procedure reset_id as
set identity_insert sales_daily on
insert into sales_daily (syb_identity, stor_id)
values (102, "1349")
select ##identity
select ##identity
execute reset_id