Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Instead Of Insert Trigger

Author  Topic 

notmyrealname

98 Posts

Posted - 2010-10-25 : 11:50:09
Hi,

I have a question regarding Instead Of triggers.

I want to create a trigger that replaces one value of what the user is trying to insert. For instance, the user is adding a new row to a table that has 50 columns. I want to make the value in Col10 equal a value determined by a query againt the data that already resides in the table. I have no problem calculating the value i want assigned to Col10.

My question is:

Is there a way to just overwrite Col10 before it is added to the table? Should i use Instead Of Insert, After Insert, etc...?

If i use Instead Of Insert i could completely control the data that goes into the table and this is most likely what i want to do. The only thing i don't want to do is explicitly define all 50 columns again just to update the Col10 value.

I know i can do this:

INSERT INTO MyTable SELECT * FROM Inserted

This would do exactly what the Insert would do anyway. Is there any way to just update the Col10 value only?

Unforetunately i cannot do this:

UPDATE Inserted SET Col10 = MyValue

Does anyone know a way to just update Col10 before the data is added to the table?

Is there a way to declare a table variable that is already structured to match MyTable? Then i could just update the Col10 in my table variable and insert the results into the actual datatable.

Thanks.

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2010-10-25 : 12:32:09
Why don't you use a computed column instead?

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-25 : 12:45:54
Basically, the user might add a record today and make a change to the Col10 value. Tomorrow he will add the same row again. When he inserts the new row i want to update the Col10 value to match the value he set the other row to. If there is no existing match then the new row is just inserted "as is". I don't think i can achieve what i am looking fo with computed columns. I might be wrong.

Thanks.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2010-10-25 : 12:54:49
An instead of trigger sounds like the right thing here then.

You'll need to explicitly list the columns out. That shouldn't be a problem though as Management Studio can do that for you via the right click options on the table.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-25 : 13:00:15
Unforetunately i don't have Management Studio. Just Visual Studio 2005. I don't think i have options to automate the process. But at least i now know what i have to do.

One more question, please.

If MyTable is the table that i am applying the trigger to - do you know if there is a way to create a Table variable that can inherit MyTable's structure or would i also have to explicity create all of the table columns? I am just trying to avoid having to update several objects when i add new columns to this table later.

Thanks for your help.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2010-10-25 : 13:05:31
A table variable won't help you here.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-25 : 13:24:27
Wouldn't i be able to...

1. DECLARE @MyTable AS Table equal to MyTable's structure
2. Set the Col10 value for @MyTable
3. INSERT INTO MyTable SELECT * FROM @MyTable

Is there something object or variable that i can modify and then provide at the end of my INSERT command?

Sorry for the sophomoric questions? I haven't really worked much with triggers and Table variables. I'll stop asking after this, i promise!

Thanks again.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2010-10-25 : 13:39:24
We can certainly write elaborate code to do what you want, however it'll only slow down your trigger (which is not a good idea as the trigger participates in a transaction).

Could you get SQL Server Management Studio Express installed to help you with this? It's a free download and will greatly help you out with SQL Server development.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-25 : 13:45:19
quote:
Originally posted by tkizer

Could you get SQL Server Management Studio Express installed to help you with this? It's a free download and will greatly help you out with SQL Server development.
Could you please call my IT guy? I've been asking for years!

Thanks for all the advice. It's not the end of the world to explicitly define the columns in my update. I'll give it a try.

Thanks again.
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-25 : 20:11:21
After a little more research it actually turned out to be pretty simple. Unless i am missing something.


ALTER TRIGGER InterceptNewValue
ON ActualTable
INSTEAD OF INSERT
AS

-- Create a temp copy of the Inserted table
SELECT * INTO #MyTable FROM Inserted

-- Update my temp table as needed.
-- The logical table Inserted cannot be updated
-- with an UPDATE query.
UPDATE #MyTable SET [AnyColumn] = (SELECT ... FROM MyTable ...)

-- Insert data from temp table instead of the
-- data in the Inserted table.
INSERT INTO ActualTable SELECT * FROM #MyTable


Now i don't have to worry about updating this trigger if i make changes to the ActualTable structure (i.e. add, remove, rename columns). I just have to make sure that the [AnyColumn] column does not change.

Still deciding if i should do this with the trigger or set the value in my application (ADO.Net).

Anyway, thought i'd keep you posted.

Thanks.
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2010-10-25 : 23:26:09
Cool, looks good.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-10-26 : 02:21:46
Why not use an AFTER trigger?


ALTER TRIGGER InterceptNewValue
ON ActualTable
AFTER INSERT
AS
UPDATE U
SET [AnyColumn] = (SELECT ... FROM MyTable ...)
FROM ActualTable AS U
JOIN inserted AS I
ON I.MyID = U.MyID
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-26 : 08:48:33
quote:
Originally posted by Kristen

Why not use an AFTER trigger?

It's kind of complicated. How do i explain?

Let's say the following info is already in the table...

Part SomeValue
------ ----------
100 123
101 123
101 123
101 123


You'll notice that the same part can be entered many times. You can also see that the SomeValue will always be the same for each unique part (i.e. Part 101 has SomeValue = 123). I have an UPDATE trigger in place to ensure that the SomeValues always remain the same.

Now...

Let's say i have a new value being added to the table.

Part SomeValue
------ ----------
101 NULL


I want to first look and see if the part already exists in the table. If it does, then i want the newly added SomeValue to inherit the existing SomeValue for that part. If it doesn't already exist then part can be added as is. Because i know that the SomeValues are always the same for each part, i can just select the first matching part and copy its SomeValue to the new part.

The problem with the AFTER trigger is that my data would now look like this...

Part SomeValue
------ ----------
100 123
101 123
101 123
101 123
101 NULL


Now i have no way of determining which SomeValue was the original unless i add some timestamp which i could do but i just don't want to.

Let me point out that i am still pretty new to these differnt variations of triggers. That is how i think the AFTER trigger works. Please correct me if i am wrong. Is there a way using an AFTER trigger to capture the existing data before the trigger fires and then perform the update after?

Thanks for the suggestion. I really appreciate the help.

Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-10-26 : 08:56:07
So you have no Primary Key on the table, and no combination of columns that are unique?

(If so its not a good table design! I'm afraid)
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-26 : 09:06:09
Sorry. The table was just an example to illustrate the columns that needed to be analyzed. There are in fact unique part id's. The primary key is actually [Project, PartID].
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-10-26 : 09:11:10
In that case:

ALTER TRIGGER InterceptNewValue
ON ActualTable
AFTER INSERT
AS
UPDATE U
SET [AnyColumn] = (SELECT ... FROM MyTable ...)
FROM ActualTable AS U
JOIN inserted AS I
ON I.Project = U.Project
AND I.PartID = U.PartID

Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-10-26 : 09:13:37
Note that the value will be "wrong" between the actual INSERT and until the Trigger has finished. BUT ... that is within a transaction, so nothing else will be able to see the intermediate value (unless some twit uses the NOLOCK hint or somesuch) ... but it would create a problem if, for example, you had a CHECK CONSTRAINT on the column that was violated - e.g. if you are saving this value with a NULL in this column, relying on the Trigger to "fix up" the actual value, but the underlying table does not allow NULLs
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-26 : 09:20:34
So is the AFTER INSERT an additional event that happens after the default INSERT whereas the INSTEAD OF INSERT completely replaces the default INSERT?

So in your trigger, does the data in the ActualTable have (at the time the trigger fires) the new value in it? Wouldn't this still prevent me from determining what the existing value is without adding some sort of timestamp column?

Thanks.
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-10-26 : 09:36:27
1. Yes
2. When the trigger files [ActualTable] contains the new data (not-yet-modified by your trigger), and [INSERTED] pseudo-table has the same data (but only for row(s) which are part of the Insert [and in a DELETE or UPDATE the [DELETED] pseudo-table has the original data, before the Delete/Update happened]
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-10-26 : 09:38:16
Note that an AFTER trigger doesn't need special logic to make sure it can always handle all modifications to the table, so I think it is preferable in this scenario (unless someone tells me that the fact that an AFTER triggers causes two-updates to happen is Bad News!)
Go to Top of Page

notmyrealname

98 Posts

Posted - 2010-10-26 : 09:58:32
Alright. I'll see if i can implement it. Thanks.
Go to Top of Page
    Next Page

- Advertisement -