Trigger that inserts data into new table when another table is updated - sql-server

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

Related

MSSQL update set from output clause

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;

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.

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!

Microsoft SQL server: have one auto-incrementing column update another table

I have a table of orders with orderID. I want when I create a new row in orders, and automatically have it add the same orderID to a new row in orderDetails. I got the auto incrementing to work, however whenever I try to link the two, adding cascade delete, it gives me an error.
'order' table saved successfully
'orderDetail' table
- Unable to create relationship 'FK_orderDetail_order'.
Cascading foreign key 'FK_orderDetail_order' cannot be created where the referencing column 'orderDetail.orderID' is an identity column.
Could not create constraint. See previous errors.
Which seems to be because of the fact there is no orderID at row creation. Without these two linked it's pretty hard to link an order to its information.
I am using Microsoft SQL server mgt studio. I learned via command-line MySQL, not SQL, so this whole GUI stuff is throwing me off (and I'm a tad rusty).
Your problem is that 'orderDetail.orderID' should not be an identity column (auto-incrementing). It should be based on the orderId in the Order table. You can do that in a variety of ways. If you are using stored procedures, and making separate calls to the database for the orderDetail records, have the code save the order row first, and return the newly created OrderId value, then use that value on the calls to save orderdetails. If you are making one call to a stored proc that saves the order header record and all order detail records in one call, then in the stored procd, insert the ordfer record forst, use Scope_identity() to extract the newly created orderId into a T-SQL variable,
Declare #orderId Integer
Insert Orders([Order table columns])
Values([Order table column values])
Set #orderId = scope_Identity()
and then use the value in #orderId for all inserts into the OrderDetails table...
Insert OrderDetails(OrderId, [Other OrderDetail table columns])
Values(#orderId , [Other OrderDetail table column values])
You want a AFTER INSERT trigger on the order table - in this, the newly given ID is available as NEW.orderID and can now easily be inserted into orderDetails.
Just do this via the command line. I certainly do.

SQL Server 2005 How can I set up an audit table that records the column name updated?

given this table definition
create table herb.app (appId int identity primary key
, application varchar(15) unique
, customerName varchar(35),LoanProtectionInsurance bit
, State varchar(3),Address varchar(50),LoanAmt money
,addedBy varchar(7) not null,AddedDt smalldatetime default getdate())
I believe changes will be minimal, usually only a single field, and very sparse.
So I created this table:
create table herb.appAudit(appAuditId int primary key
, field varchar(20), oldValue varchar(50),ChangedBy varchar(7) not null,AddedDt smalldatetime default getdate())
How in a trigger can I get the column name of the value of what was changed to store it? I know how to get the value by joining the deleted table.
Use the inserted and deleted tables. Nigel Rivett wrote a great generic audit trail trigger using these tables. It is fairly complex SQL code, but it highlights some pretty cool ways of pulling together the information and once you understand them you can create a custom solution using his ideas as inspiration, or you could just use his script.
Here are the important ideas about the tables:
On an insert, inserted holds the inserted values and deleted is empty.
On an update, inserted holds the new values and deleted holds the old values.
On a delete, deleted holds the deleted values and inserted is empty.
The structure of the inserted and deleted tables (if not empty) are identical to the target table.
You can determine the column names from system tables and iterate on them as illustrated in Nigel's code.
if exists (select * from inserted)
if exists (select * from deleted)
-- this is an update
...
else
-- this is an insert
...
else
-- this is a delete
...
-- For updates to a specific field
SELECT d.[MyField] AS OldValue, i.[MyField] AS NewValue, system_user AS User
FROM inserted i
INNER JOIN deleted d ON i.[MyPrimaryKeyField] = d.[MyPrimaryKeyField]
-- For your table
SELECT d.CustomerName AS OldValue, i.CustomerName AS NewValue, system_user AS User
FROM inserted i
INNER JOIN deleted d ON i.appId = d.appId
If you really need this kind of auditing in a way that's critical to your business look at SQL Server 2008's Change Data Capture feature. That feature alone could justify the cost of an upgrade.
something like this for each field you want to track
if UPDATE(Track_ID)
begin
insert into [log].DataChanges
(
dcColumnName,
dcID,
dcDataBefore,
dcDataAfter,
dcDateChanged,
dcUser,
dcTableName
)
select
'Track_ID',
d.Data_ID,
coalesce(d.Track_ID,-666),
coalesce(i.Track_ID,-666),
getdate(),
#user,
#table
from inserted i
join deleted d on i.Data_ID=d.Data_ID
and coalesce(d.Track_ID,-666)<>coalesce(i.Track_ID,-666)
end
'Track_ID' is the name of the field, and d.Data_ID is the primary key of the table your tracking. #user is the user making the changes, and #table would be the table your keeping track of changes in case you're tracking more than one table in the same log table
Here's my quick and dirty audit table solution. (from http://freachable.net/2010/09/29/QuickAndDirtySQLAuditTable.aspx)
CREATE TABLE audit(
[on] datetime not null default getutcdate(),
[by] varchar(255) not null default system_user+','+AppName(),
was xml null,
[is] xml null
)
CREATE TRIGGER mytable_audit ON mytable for insert, update, delete as
INSERT audit(was,[is]) values(
(select * from deleted as [mytable] for xml auto,type),
(select * from inserted as [mytable] for xml auto,type)
)

Resources