June 7, 2005 at 8:33 am
I have a stored procedure that doesn't always do the update I expect it to, so I want to set up a Profiler trace. I don't care about the events from any other stored procedure, function, or SQL statement. The SP I want to trace has some input parameters, so I'd like to see them. It has an output parameter, so I'd like to see that. It uses dynamic SQL, so if there's something specific I should be looking at related to that, I'd like to see that as well. I'd like to see that it starts, and that it finishes.
I've tried restricting by TextData and ObjectName, but I'm still getting way too many events, and absolutely killing the application's response time. So my question is, what events, data columns, and filters do I need to accomplish this?
Thanks in advance for any help on this. It's frustrating enough having a stored procedure not work.
Mattie
June 7, 2005 at 8:39 am
have you tried running the debugger on the proc (query analyser, right click in the proc/debug)?
June 7, 2005 at 8:48 am
Remi,
Thanks for responding. As for using QA, I have, and it runs fine. In fact, it runs fine most times it executes in my application. The problem seems, at least to me, very similar to the one described in http://www.sqlservercentral.com/forums/shwmessage.aspx?forumid=5&messageid=186841, so I was really hoping for a resolution to that one, but no such luck.
Mattie
June 7, 2005 at 8:52 am
Ya it's a shame that we didn't hear from him again. But I'm not sure you understood what I meant bu running the debugger on the proc. Are you aware that there is a debugger that can run the proc line by line just like in vb?
If you know with which parameters it fails, then you can copy that proc under a new name and debug it on the server (unless you already have a test server for this stuff).
Then you can add print statements too see which parts on the proc is being run and what are the variables value.
Or you could paste it here so we can have a look.
June 7, 2005 at 9:12 am
No, I understood about running it thru the QA debugger. It doesn't fail there. In fact, after it has failed in the application, and the user logs out of the app, then logs back in, and presses the same button, it works fine. And I've never been told that it fails when the user executes it the first time.
Now this is probably going to give Frank Kallis a heart attack, but here's what the stored procedure does. It passes in a record number and a string that contains the SET statement for the update. Before it does the update, however, it inserts the existing data into a history table, using more dynamic SQL. If that's successful (which doesn't seem to be the case when this process doesn't work), it then does the update. If the update is successful, it commits the transaction, otherwise it rolls it back.
I'm going to follow this post with another one that contains the code, slightly obscured.
Mattie
June 7, 2005 at 9:17 am
Let me send an ambulance to Frank's house before you post this...
I'll be waiting for mine here on the floor.
June 7, 2005 at 9:26 am
Here's the procedure, and don't claim you weren't warned. Let me also make the following points. First, I now know that this couldn't violate more rules of stored procedures than if that had been what I set out to do. Two, there's nothing I can do about it right now. Three, god-awful as it is, it does exactly what I need it to do, when it decides to execute, which is almost all of the time. And finally, yes, I'm being very defensive, but please don't take it as a reflection on you. I'm very grateful for whatever help anyone can offer.
CREATE PROCEDURE stp_TableUpdate
@MyUID nvarchar(10),
@MySet nvarchar(1600),
@ArchiveInd int,
@ArchivedBy nvarchar(20),
@ArchivedOn nvarchar(1000),
@HistoryIdentity int output as
BEGIN
--all processes
DECLARE @ReturnError int
DECLARE @sql nvarchar(2100)
DECLARE @SQLSetError nvarchar(100)
DECLARE @SQLSetCount nvarchar(100)
--update process
DECLARE @SQLUpdate nvarchar(1000)
DECLARE @SQLWhere nvarchar(100)
DECLARE @UpdateParmDefinitions nvarchar(200)
DECLARE @UpdateReturnError int
DECLARE @UpdateRecordCount int
--insert process
DECLARE @InsertParmDefinitions nvarchar(100)
DECLARE @HistoryRecordCount int
DECLARE @SQLInsert nvarchar(1000)
DECLARE @SQLSelect nvarchar(1000)
DECLARE @SQLIdentitySet nvarchar(100)
DECLARE @ParmValues nvarchar(200)
SET @ReturnError = 0
BEGIN TRAN
IF @ArchiveInd = 1
BEGIN
SET @SQLInsert = 'INSERT INTO MyTableHistory
(ServiceUID, ServiceDate, Counter, ServicePeriod, ServiceType, ServiceReason, ClaimedMiles, ServiceHours, ServiceDesc, Remarks, ServiceAmt, MileageAmt, MileageTaxableInd,TollsAmt, FY, PayPeriod, SchedulingUID, Status, StatusBy, StatusOn, CreatedBy, CreatedOn, ModifiedBy, ModifiedOn, CancelledBy, CancelledOn, CancelledDesc, AuthorizedBy, AuthorizedOn, PaidOn, TravelFrom, ArchivedOn, ArchivedBy) '
SET @SQLSelect = 'SELECT UID, ServiceDate, Counter, ServicePeriod, ServiceType, ServiceReason, ClaimedMiles, ServiceHours, ServiceDesc, Remarks, ServiceAmt, MileageAmt, MileageTaxableInd, TollsAmt, FY, PayPeriod, SchedulingUID, Status, StatusBy, StatusOn, CreatedBy, CreatedOn, ModifiedBy, ModifiedOn, CancelledBy, CancelledOn, CancelledDesc, AuthorizedBy, AuthorizedOn, PaidOn, TravelFrom, ArchivedOn = @ParmArchivedOn, ArchivedBy = @ParmArchivedBy ' + ' FROM MyTable WHERE UID = ' + @MyUID
SET @SQLIdentitySet = ' SET @ParmScopeIdentity = SCOPE_IDENTITY() '
SET @sql = @SQLInsert + @SQLSelect + @SQLIdentitySet
SET @InsertParmDefinitions = '@ParmScopeIdentity int output, @ParmArchivedBy varchar(20), @ParmArchivedOn datetime'
EXECUTE sp_executesql @SQL,
@InsertParmDefinitions,
@ParmScopeIdentity=@HistoryIdentity output, @ParmArchivedBy = @ArchivedBy, @ParmArchivedOn = @ArchivedOn
SELECT @HistoryRecordCount = @@RowCount, @ReturnError = @@Error
END
IF @ReturnError <> 0
OR @HistoryRecordCount = 0
OR @HistoryIdentity = 0
RETURN @ReturnError
SET @SQLUpdate = 'UPDATE MyTable '
SET @SQLWhere = ' WHERE UID = ' + @JSUID
SET @SQLSetError = ' SET @ParmUpdateReturnError = @@Error'
SET @SQLSetCount = ' SET @ParmUpdateRecordCount = @@Rowcount'
SET @sql = @SQLUpdate + @MySet + @SQLWhere + @SQLSetError + @SQLSetCount
SET @UpdateParmDefinitions = '@ParmUpdateReturnError int output, @ParmUpdateRecordCount int output'
EXECUTE sp_executesql @sql,
@UpdateParmDefinitions,
@ParmUpdateReturnError=@UpdateReturnError output, @ParmUpdateRecordCount = @UpdateRecordCount output
IF @UpdateReturnError > 0
OR @UpdateRecordCount = 0
BEGIN
SET @ReturnError = @UpdateReturnError
ROLLBACK TRANSACTION
END
ELSE
COMMIT TRANSACTION
RETURN @ReturnError
END
GO
June 7, 2005 at 11:23 am
Sorry for the delay, I just got released from the hospital.
Well first of all, you don't rollback the transaction after the first sp_executesql when there's an error. Is this what you want?
Maybe this will help you figure out the problem : right before the first return, I would insert the values of all the parameters used to set the @sql variable and the @sql variable into a log table. This would give you an idea of why this is failing.
Also is it possible that you blow past 2100 characters when you build the string (seems to me that if all the variables are maxed out, they could add up to more than 2100 characthers)?
June 7, 2005 at 12:32 pm
Released from the hospital would be this icon I suppose.
I don't explicitly rollback the transaction after the first sp_executesql because I thought that exiting the SP without committing achieved the same thing. Is this an incorrect assumption?
As for the length, I don't think that's a problem, because what can be updated when the update doesn't occur is very limited. Under other circumstances, where it doesn't fail, the update can be much longer. And I would hope that returning the error code would give me a clue that something had failed, but it never does.
That said, I'm going to try your suggestion about the log table. Although I wonder about the logic of using an insert statement to determine why an insert/update statement doesn't work. (Like fighting fire with fire?)
Are there any good references on Profiler?
Thanks,
Mattie
June 7, 2005 at 12:41 pm
Sounds like an assumption of code execution to me (like the order by should be by the primary key if none is specified)... Nothing good can come out of this with sql server (because there are way too many features than can change the "default behavior").
I can't really answer your auto rollback question on that end, but one of these 3 articles will surely be able too :
All about transaction Part III
I've never used the profiler to log the failure of code execution.. maybe someone else can shed some light on this process (if it's even possible).
June 7, 2005 at 12:45 pm
BTW, the point of logging the statement is to be able to rerun it and see if it's a compile or execution error and then fix the problem... fix is hard to do when you have no idea of why it's failing, but I guess you had already figured that part out.
June 8, 2005 at 11:10 am
Remi,
Well, as always happens when I'm trying to isolate why something fails intermittently, everything they tried today worked. So I'll keep my log table going until the process fails, and then I'll see if I can spot a difference (parameters, execution time).
Thanks for your help. If I figure anything out, I'll post it.
Mattie
June 8, 2005 at 11:14 am
HTH... this might sound strange... but I hope it fails again .
June 8, 2005 at 11:15 am
Did you add the missing rollback too?
If yes, then try removing it too see if it fails again.
June 8, 2005 at 11:20 am
No, I haven't added in the rollback yet. Incredibly enough, it's more important to me to track what's happening when it fails than to have it not fail. So far, I'm much more frustrated with this problem than my users are.
Viewing 15 posts - 1 through 15 (of 15 total)
You must be logged in to reply to this topic. Login to reply