MSSQL update set from output clause - sql-server

Context
I got a temporary table which is filled/adjusted by users. Let's call the table tmp, with columns ID, updated_at, price, foreign_ID. Every time the user enters a new price, the price column is filled and the updated_at and ID are created automatically. foreign_ID is NULL until the record is processed to another table, when my foreign_ID should contain the ID of the other table.
Periodically I update a table with prices, let's call it prices. Here are all prices stored from different sources, among them from the tmp table. The prices table has the columns ID, updated_at, price.
question
I want to insert the data from my tmp table into prices table, and update the column foreign_ID with the corresponding ID from my prices table. How can I insert new rows in a table and update/set a IDs in another table?
My desired result after the periodic update is a new entry in the prices table with the new prices which were not yet processed, and a foreign_ID in my tmp table which corresponds with the ID in my prices table.
I know I can output the inserted IDs using the following query:
insert into prices
output inserted.ID
select price
from tmp;
I'm struggling to see how I can use the inserted.ID to update my tmp.foreign_ID column with the output above.
Help is appreciated!

You can also INSERT the values from the OUTPUT clause into another table as well, so if you need those you can still reference them.
Without proper sample data and behaviour, this is just an example but should, hopefully, set you on the right path as it shows you how to get the values from inserted into another object. You can then use that object to do the additional task(s) you need:
CREATE TABLE dbo.SomeTable (ID int IDENTITY(1,1),
SomeString varchar(10));
GO
DECLARE #IDs table (ID int);
INSERT INTO dbo.SomeTable (SomeString)
OUTPUT inserted.ID
INTO #IDs (ID)
VALUES('asdjgkde'),('sdflhdglf');
SELECT *
FROM #IDs;
GO
DROP TABLE dbo.SomeTable;

Related

SQL Insert does column order matter

I have two tables with the same field names and a stored procedure that updates table B with Table A's data by doing a delete from current table and insert into current table from another table that has update values in it:
delete from ac.Table1
insert into ac.Table1
select *
from dbo.OriginalTable
where dtcreate <getdate()-1
I had to recreate Table1 through GIS software which adds GlobalIDs and an Object ID field. The original order had Object ID at the end and the new table has it at the front. Will this impact executing the SQL statement above?
Yes it will. The order of the columns should match for each value to go in desired column
You can try
Insert into ac.Table1 (column1....columnN)

How to insert record into table which is having 6054 records

I am having one table with 3 f_Key and 1 P_Key with 6054 records.
One record is lost from that table. I am trying to insert record into that table.
The record id is 2352 and last record id is 9560 so,if i insert the record then it is taking 9561 id which is next id of before id.If try to delete the others records then because of F_Key it is not allowing to delete also.If i try to update the 9561 id then it also not allowing to update.
You can use the SET IDENTITY INSERT construct to explicitly insert the PK value in a table with auto-numbering, like so:
set identity_insert #your_table on
insert into your_table (PK_COL_IDENTITY, ...) values (2352, ...)
set identity_insert #your_table off
As per my knowledge , if your ID is auto incremented then you cannot update that ID(key) .The only way to do in your case is TRUNCATE.If you will truncate the table then it will allow to generate new sequence.
You can create a temporary table and migrate the data to temporary table and truncate that parent table and again migrate the data from temporary table to parent table.
Hope it will help you.

What is the use of OUTPUT clause in sql server

What is the purpose of the OUTPUT clause? I have gone through the MSDN documentation for the OUTPUT clause, which includes the following example:
DELETE FROM dbo.table1
OUTPUT DELETED.* INTO #MyTableVar
WHERE id = 4 OR id = 2;
From the above query, it seems that deleted records are saved in some magic table called deleted, and the query will load those records into table called MyTableVar from the magic deleted table. .
I still do not understand the purpose of the OUTPUT clause usage.
As another SQL example:
USE AdventureWorks2012;
GO
DECLARE #MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO #MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM #MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
GO
What is this actually doing? Can anyone explain what this clause is doing with an easy example?
UPDATE with non-functioning example:
create proc test
as
CREATE TABLE dbo.table1
(
id INT,
employee VARCHAR(32)
)
go
INSERT INTO dbo.table1 VALUES
(1, 'Fred')
,(2, 'Tom')
,(3, 'Sally')
,(4, 'Alice')
delete from table1
select * from deleted
This gives me an error when I run it, because it can't see the deleted table.
The general purpose of this clause is to capture the changes made to your data without an additional query, which would introduce locking and blocking issues. Example:
DELETE FROM X WHERE Name = 'Foo'
You want to know which IDs were deleted. You can do this naively like this:
SELECT ID FROM X WHERE Name = 'Foo'
DELETE FROM X WHERE Name = 'Foo'
But these selected IDs are unreliable unless you are running in a transaction with isolation level SERIALIZABLE which is usually not the case. Someone else can add, delete or change "Foo"-Records between your two statements. So instead you can use the OUTPUT clause and get back exactly and reliably the deleted IDs without any performance or reliability issues.
Another frequent use is to get the value of inserted default values, especially when using identity columns. For a single insert you can do this:
CREATE TABLE X
(
ID INT IDENTITY,
Name VARCHAR(10)
);
INSERT X (Name) VALUES ('Foo')
SELECT SCOPE_IDENTITY()
But SCOPE_IDENTITY() can give you only the last inserted ID. If you do multiple inserts, like
INSERT X (Name) VALUES ('Foo'), ('Bar')
or
INSERT X (Name) SELECT OtherName FROM Y
and you want to know the inserted IDs, you are out of luck. You can try to find them with another SELECT, but you need another unique column to even formulate the query and then you run into the same issues as with the DELETE sample above. So, the OUTPUT clause lets you identify neatly which Names got which IDs.
You will need these IDs for example when creating dependent records with foreign keys. Think "Order" and "OrderDetails" which are linked by an OrderID column with an IDENTITY clause. Again, with a single INSERT you can get away with using SCOPE_IDENTITY() or ##IDENTITY, but when inserting multiple orders at once, you will need OUTPUT.
When you perform Insert/Update/Delete operation on particular table and want to know what rows are affected OR want to log them for audit trail OR you want to use multiple values of affected rows in subsequent sql statements, you can use OUTPUT clause.
For Insert statement, it will have INSERTED table.
For Delete statement, it will have DELETED table. In case of Update DELETED table will contain rows (with old values) before update operation performed.
For Update statement, it will have DELETED and INSERTED tables.
DELETED table will contain rows (with old values) before update operation performed.
INSERTED table will contain rows (with new values) after update operation performed.
USE AdventureWorks2012;
GO
DECLARE #MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO #MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM #MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
Now your query inserts rows in Production.ScrapReason as well as table variable #MyTableVar. Later it selects inserted rows from Production.ScrapReason and #MyTableVar. Thus you can compare both the resultset and it must have identical rows (considering Production.ScrapReason is empty table.)
I hope it makes sense!
Edit:
Inserted/Deleted tables will be available with Insert/Update/Delete statement and not after that. You may want to store those magic table values in db table or temp table.
Without the OUTPUT clause, how would you know which rows were deleted? Your example seems so simple because you already know the Id values, but what if you did this:
DELETE FROM T WHERE SomeColumn LIKE 'SomePattern%'
And you want to find out what was deleted. That's the purpose of the OUTPUT clause.

Trigger that inserts data into new table when another table is updated

I created a Modified Order table, and did not insert any data into it. This table is supposed to have an entry made every time someone updates the order table. I created a trigger that stated that if you update a row in the Order table it triggers an entry into the Order Modified table. It works properly, the only problem is I do not know how to get the Order ID that was updated to be entered into the Order modified table.
Order Modified Table Code:
Create Table Modified_Order (
Modified_Order_Number Int Identity (1,1),
Modified_Order_Date Date,
Order_ID Int,
Foreign Key (Order_ID) references Orders (Order_ID)
);
Trigger Code:
Create Trigger Modified_Order_Trigger
On Orders After Update
AS
Insert Into Modified_Order Values (getdate(), )
;
The issue I am having is getting the Order ID for the order that was updated to show up in the Order Modified table. I know it comes in the spot that is left blank after getdate(). I know it has something to do with adding a select statement, I'm just not sure what to put in after the where statement so it knows to select the order ID for whatever Order was updated in the order table.
Create Trigger Modified_Order_Trigger
On Orders After Update
AS
Insert Into Modified_Order Values (getdate(), (Select Order_ID
from Order
where )
;
Thanks
Within a Trigger, the INSERTED and DELETED virtual tables have the data from both states: INSERTED has new via INSERT or UPDATE, and DELETED has old via UPDATE or DELETE. So the syntax is basically:
Create Trigger Modified_Order_Trigger
On Orders
After Update
AS
Insert Into Modified_Order (Modified_Order_Date, Order_ID)
SELECT GETDATE(), Order_ID
FROM INSERTED
For more info on Triggers, look here: http://technet.microsoft.com/en-us/library/ms189799.aspx

Stored procedure to insert record and for each run update statement

I would like to have a stored procedure which inserts rows into a table (retrieved from a select query from another table) and for each newly inserted row gets its identity and updates the original table with the identity
Pseudo code-
records = select id,city,state,country from USER where name=#name
for each record in records // for each rows selected
insert into LOCATION(city,state,country) values(#record.city,#record.state,#record.country); //inserts a value into LOCATION table
#id = SCOPE_IDENTITY(); // gets the identity of the newly inserted row
update USER set LocationId=#id where Id=#record.id //updates the new id back to old table's column
end
This is a data migration task, where we want to segregate the LOCATION from USER table
Thanks in advance for your time and effort for this thread.
You could do something like this:
DECLARE #InsertedValues TABLE (ID INT, City VARCHAR(50), State VARCHAR(50), Country VARCHAR(50))
INSERT INTO dbo.Location(City, State, Country)
OUTPUT Inserted.ID, Inserted.City, Inserted.State, Inserted.Country INTO #InsertedValues(ID, City, State, Country)
SELECT City, State, Country
FROM dbo.YourSourceTable
With this, you now have the inserted values - including the newly defined identity values - in your #InsertedValues table variable and you can now update the source table as you see fit.
UPDATE dbo.YourSourceTable
SET
Col1 = iv.Col1,
Col2 = iv.Col2, -- etc. - do whatever you nee to do here!
FROM #InsertedValues iv
WHERE ......... -- here, you need some condition to link the inserted values to the original table
This doesn't require any cursor or any other messy RBAR (row-by-agonizing-row) processing at all - everything is nicely set-based and as fast as it can possibly be.
Learn more about the OUTPUT clause at MSDN SQL Server Books Online - you can use the OUTPUT clause on insert, update and even delete statements, too!

Resources