I'm trying to write a trigger that get a QuoteNumber from table 1 and insert it into table 2 where ShippingIdentity matches the records in both tables. The problem is the QuoteNumber is being inserted into it's own row(record) Can anyone please let me know why? Thanks.
ALTER TRIGGER InsertQuoteNumber
ON AccountInfo
FOR INSERT
AS
BEGIN
INSERT INTO ShippingInfo (QuoteNumber)
SELECT a.QuoteNumber
FROM AccountInfo a
inner join inserted i on a.ShippingIdentity = i.ShippingIdentity
END
You use the word "insert" in your description, but I think what you mean is "update". That is, you want to modify an existing row in ShippingInfo to reflect the new quote number.
The problem in your code is as simple as your choice of words. You are using an INSERT command, which inserts a new row. If you want to update an existing row, use an UPDATE.
Related
When insert I need edit a value if it is null. I create a trigger but I don't know how to edit inserted table.
ALTER TRIGGER [trigger1] on [dbo].[table]
instead of insert
as
declare #secuencia bigint, #ID_PERSONA VARCHAR;
select #secuencia = SECUENCIA from inserted
select #ID_PERSONA = ID_PERSONA from inserted
if #secuencia is null begin
set inserted.SECUENCIA = NEXT VALUE FOR SEQ_BIOINTEG --(Sequence)
end
i dont know how to edit inserted table.
You do not. That table is read only.
Note how your trigger also says:
instead of insert
There is no way to edit the inserted table.
What you do instead, is setting up an INSERT command for the original table, using the data from the inserted table to filter to the ROWS of inserted - mostly by a join.
Changing inserted makes no sense, logically - because triggers in SQL are one of two things:
INSTEAD OF - then there is no actual insert happening for inserted to start with. Instead of doing the insert, the trigger is called. As such, changing inserted - makes no sense.
AFTER - then the insert already happened (and you UPDATE the rows). As the trigger runs after the update, changing inserting makes no sense.
Note that I say ROWS - your trigger has one very basic error: it assumes inerted contains ONE row. It is a table - it is possible the changes come from an insert statement that inserts multiple rows (which is trivial, i.e. select into, or simply an insert with values for multiple rows). Handle those.
select #ID_PERSONA = ID_PERSONA from inserted
Makes NO sense - inserted is a table, so ID_PERSONA from inserted contains what value, if 2 rows are inserted? You must treat inserted like any other table.
Apart from all the varied issues with your trigger code, as mentioned by others, the easiest way to use a SEQUENCE value in a table is to just put it in a DEFAULT constraint:
ALTER TABLE dbo.[table]
ADD CONSTRAINT DF_table_seq
DEFAULT (NEXT VALUE FOR dbo.SEQ_BIOINTEG)
FOR SECUENCIA;
I've read and tried other posts/answers but am having a hard time getting this to work. I feel like it should be pretty simple for an experienced SQL programmer, but for me I'm ready to ask for help.
When I insert a record into the HistoricalWorkorders table, I simply want to delete any records with the same workorder # in the ActiveWorkorders table.
I'm trying to accomplish this using a trigger on insert.
I started simple by using the following code to insert into ActiveWorkorders every time a record is inserted into HistoricalWorkorders. That code works.
How do I modify this query such that upon insert to the HistoricalWorkorders table, any records with the same workorder # within the ActiveWorkorders table get deleted?
On a seperate note, everyone says you can reference the inserted record simply by referencing 'inserted', but it doesn't work for me? For example, shouldn't inserted.workorder return the workorder value being inserted to the table?
ALTER trigger [dbo].[WOArchive] on [dbo].[HistoricalWorkOrders]
after update,insert
as
begin
insert into ActiveWorkorders
(Workorder,Grindcount,Status)
select i.workorder, i.grindcount, i.status
from HistoricalWorkorders t
inner join inserted i on t.workorder=i.workorder
end
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
If only one row with a distinct field is to be updated,I can use:
insert into tab(..) value(..) on duplicate key update ...
But now it's not the case,I need to update 4 rows inside the same table,which have its field "accountId" equal to $_SESSION['accountId'].
What I can get out of my mind at the moment is:
delete from tab where accountId = $_SESSION['accountId'],
then insert the new rows.
Which obviously is not the best solution.
Has someone a better idea about this?
Use the update just like that!
update tab set col1 = 'value' where accountId = $_SESSION['accountId']
Moreover, MySQL allows you to do an update with a join, if that makes your life a bit easier:
update
tab t
inner join accounts a on
t.accountid = a.accountid
set
t.col1 = 'value'
where
a.accountname = 'Tom'
Based on your question, it seems like you should review the Update Statement.
Insert is used to put new rows in - not update them. Delete is used to remove. And Update is used to modify existing rows. Using "Insert On Duplicate Key Update" is a hackish way to modify rows, and is poor form to use when you know the row is already there.
load all of the values in to a temporary table.
UPDATE all of the values using a JOIN.
INSERT all of the values from the temp table that don't exist in the target table.
You can use replace statement. This will work as a DELETE followed by INSERT
I wish to make a trigger but i'm not sure how to grab the data for whatever caused the trigger.
I have a simlpe table.
FooId INT PK NOT NULL IDENTITY
Name VARCHAR(100) NOT NULL
I wish to have a trigger so that when an UPDATE, INSERT or DELETE occurs, i then do the following.
Pseduocode
IF INSERT
Print 'Insert' & Name
ELSE IF UPDATE
Print 'Update' & FooId & Name
ELSE IF DELETE
Print 'Delete' & FooId & Name
Now, I know how to make a trigger for a table.
What i don't know how to do is figure out the values based on what the trigger type is.
Can anyone help?
Edit: Not sure if it helps, but db is Sql Server 2008
the pseudo table "inserted" contains the new data, and "deleted" table contains the old data.
You can do something like
create trigger mytrigger on mytable for insert, update, delete
as
if ( select count(*) from inserted ) > 0
-- insert or update
select FooId, Name from inserted
else
-- delete
select FooId, Name from deleted
To clarify all the comments made by others, on an insert, the inserted table contains data and deleted is empty. On a delete, the situation is reversed. On an update, deleted and inserted contain the "before" and "after" copy of any updated rows.
When you are writing a trigger, you have to account for the fact that your trigger may be called by a statement that effects more than one row at a time.
As others have pointed out, you reference the inserted table to get the values of new values of updated or inserted rows, and you reference the deleted table to get the value of deleted rows.
SQL triggers provide an implicitly-defined table called "inserted" which returns the affected rows, allowing you to do things like
UPDATE mytable SET mytimestamp = GETDATE() WHERE id IN (SELECT id FROM inserted)
Regarding your code sample, you'll want to create separate INSERT, UPDATE and DELETE triggers if you are performing separate actions for each.
(At least, this is the case in SQL Server... you didn't specify a platform.)
On 2008, there is also MERGE command. How do you want to handle it?
Starting from 2008, there are four commands you can modify a table with:
INSERT, UPDATE, DELETE, and MERGE:
http://blogs.conchango.com/davidportas/archive/2007/11/14/SQL-Server-2008-MERGE.aspx
http://sqlblogcasts.com/blogs/grumpyolddba/archive/2009/03/11/reasons-to-move-to-sql-2008-merge.aspx
What do you want your trigger to do when someone issues a MERGE command against your table?