November 2, 2006 at 1:13 pm
Hi all,
I have an after update trigger that bascially looks for the fields that were updated and log that information.
I am getting the column name and storing it in a variable :@colname. I want to get the column contents.
What I need is something like this:
SELECT @tcolname = ('SELECT '+@colname+' FROM deleted')
EXEC (@tcolname)
However, this does not work since deleted isn't recognized.
Another way that I tried that didn't work:
SELECT @colname FROM deleted;
In this case, the table was recognized, but @colname is the name of the column, e.g. FIRSTNAME, and not, e.g. John.
Please help..
November 2, 2006 at 2:29 pm
November 2, 2006 at 2:32 pm
Welcome to the limited and confusing and mind boggling world of dynamic sql. My guess is that 'deleted' being a 'special table' of sorts is not recognized inside the dynamic sql stored procedure, i.e. it doesn't get passed 'automatically' as you would like. A dynamically called stored procedure is in a dark world and unless you pass things to it explicitly it will know nothing about who or what called it unless you help. In this case I think there is no way.
November 2, 2006 at 3:16 pm
I have no hope of getting this resolved? (sigh)
I'll post the code tomorrow, as it's on another computer that I can't get to right now. However, I don't think that it matters as I am sure that it's getting the correct column name since, if I change the table name in:
SELECT @tcolname = ('SELECT '+@colname+' FROM deleted')
EXEC (@tcolname)
to let's say app_user, it returns the correct column results, i.e. if FIRSTNAME is passed in, then all the FIRSTNAMEs from the app_user table are printed.
November 2, 2006 at 5:05 pm
SELECT *
INTO #deleted
FROM deleted
-- you may wish to work out data some way here, e.g. delete duplications, apply trims for char values, etc.
SELECT @tcolname = ('SELECT '+@colname+' FROM #deleted')
EXEC (@tcolname)
_____________
Code for TallyGenerator
November 2, 2006 at 11:17 pm
'deleted' is a special table available within the context of a trigger. The dynamic sql doesn't know it's being called by a trigger. But the use of a temporary table suggested by Sergiy seems like a good prospect.
November 3, 2006 at 7:32 am
So, I added the following lines as advised:
SELECT * INTO #deleted FROM deleted
SELECT @tcolname = ('SELECT '+@colname+' FROM #deleted')
EXEC (@tcolname)
and this is the error I get:
"There is already an object named '#deleted' in the database."
As for the sql used to get the column name:
SELECT @colname = COLUMN_NAME from Information_Schema.Columns WHERE @field=ORDINAL_POSITION AND TABLE_NAME=@tblname
However, like I said, I don't think that this affects anything, taking into consideration that I could be wrong
November 3, 2006 at 9:48 am
So change the select to read:
SELECT * INTO #d2 FROM deleted
SELECT @tcolname = ('SELECT '+@colname+' FROM #d2')
EXEC (@tcolname)
That will eliminate the error of #deleted already being there
November 3, 2006 at 11:48 am
I should have mentioned that I tried changing the name : #deleted to #del with the same error:
"There is already an object named '#del' in the database."
In other words, I don't think it has to do with the name of the table, as I am getting the same error despite the name.
November 3, 2006 at 8:13 pm
You probably need to read BOL about temporary tables.
Where and when they are created, when dropped, what is the scope for it, etc.
_____________
Code for TallyGenerator
November 4, 2006 at 12:29 am
What is the overall problem you are trying to solve? Are you are trying to write a general purpose trigger which logs changes on an arbitrary table to a central table of the form
create table changes(
tabname varchar(50),
colname varchar(50),
oldvalue varchar(100),
newvalue varchar(100),
changedon datetime)
My big question is: why is your column name in a variable?
In any case, this kind of trigger is hard to generalize because typically to see changes you will need to link the deleted table with the inserted table through specific columns that represent a unique key and then compare the remaining columns.
November 6, 2006 at 6:23 am
So, I used a temporary table to get the value, with the code below:
--check if table exists and if it does, drop it
If Object_Id('tempdb..#temp') is Not Null
Drop table #temp
SELECT * INTO #temp FROM deleted
SELECT @tcolname = ('SELECT '+@colname+' FROM #temp')
EXEC (@tcolname)
I think the error posted earlier was caused by a loop.
Thanks for all the help.
However, I need one more step, and that's for whatever value is returned, for it to be stored in a variable.
I need something like this:
SELECT @tcolname = ('SELECT '+@colcon+'='+@colname+' FROM #temp')
However, as you might assume, it's a null value is stored in @colcon.
Any suggestions?
Please help...
November 6, 2006 at 6:33 am
As for what I am trying to achieve...
I want to log a user's update action on a specific table. However, I do not want to go checking one-for-one the fields updated, so I have decided to write a loop that would check if the field is updated and then store it in a variable. The loop is checking the substring of COLUMNS_UPDATED() to get the column.
I am storing the column name as well as the old value of the column (retrieved from the deleted table) among other values.
I am getting all the values I need except the old value of the column since I am passing in a variable as the column name. I am now able to get the value from the deleted table (as shown in the code above).
What I need now, is for that value to be stored in a variable so that I can pass it to a table to be stored.
I hope you understand? Feel free to ask any questions...
November 6, 2006 at 6:45 am
...for that value to be stored in a variable... |
Use sp_executesql like this
DECLARE @result varchar(255)
SET @sql = 'SELECT @result = ' + @colname + ' FROM #temp'
EXEC sp_executesql @sql, N'@result varchar(255) OUTPUT', @result OUTPUT
however you may have to CAST the column you are selecting to match @result or make sure it is of the correct datatype
Far away is close at hand in the images of elsewhere.
Anon.
November 6, 2006 at 7:10 am
My problem is resolved. The last step was done using David's method (as above). Thanks alot.
Thank you so much everyone! 🙂 Really couldn't have done it without you..
By the way...what do you think of the method I used? ....This should have really been my first quest no?...I needed to save on code and be able to reuse existing code...that's why I chose to go down this path
Viewing 15 posts - 1 through 15 (of 20 total)
You must be logged in to reply to this topic. Login to reply