Longshot: Is NOLOCK used in the code?
Some variations-on-a-theme, but probably not significantly different ways. There is a single-step type debugger I believe, but I've never used it in anger or heard much about it, so I presume its not the tool-of-choice for most developers when debugging
We have a parameter "@Debug" on all our Sprocs, and then
IF @Debug = 1 THEN SELECT [MySprocName] = 'DEBUG(1)', @Param1, @Param2
debugging statements within the code. If one SProc calls another then it includes the @Debug parameter - so any child-SProcs also output debugging info when passed a non-zero value.
We run the Sproc in SSMS, or similar, when we have a problem to solve and set the @Debug parameter to get the debugging information output. Our preference is to use SELECT for that, and to have the first column aliased to the name of the Sproc (so if one Sproc calls another we can see which one is outputting the debug information) and to have a value in that first column e.g. "DEBUG(1)" which uniquely identifies the location within the Sproc. We might have:
SELECT ... blah ... blah ... blah ...
FROM SomeTable
WHERE SomeColumn = @Param1
SELECT @intRowCount = @@ROWCOUNT, @intErrNo = @@ERROR
IF @debug = 1 THEN SELECT [MySprocName] = 'DEBUG(1)', [@intRowCount]=@intRowCount, [@intErrNo]=@intErrNo, [@Param1]=@Param1
which requires finding where the "DEBUG(1)" label is to see what the RowCount is referring to, but typically I am reading the code, and checking the associated DEBUG(nnn) statement in the resultset to see what the appropriate values were, which seems to work for us. I would probably then add some more debugging SELECT statements, or append more variables to the existing ones, and run the Sproc again until I had the debugging data I needed to figure out what the problem was.
If you will be needing to post-mortem examine the logging results (perhaps because the SProc takes a long time to run, or doesn't always fail) then outputting to a Logging Table would work well.
We have a single, generic, error logging table which we use for that purpose:
varchar - NAME - e.g. of the Sproc / script being run
INT - Error / Result Code value
varchar - Message - some relevant message / indicator of location within the code
varchar - Optional Values 1 to 5 - allows for output of up to 5 values. We sometimes concatenate values together to store in one the columns, e.g.
INSERT INTO MyLogTable
SELECT 'MySprocName', 1, 'DEBUG(1)', '@intRowCount=' + CONVERT(varchar(20), @intRowCount)
+ ', @intErrNo=' + CONVERT(varchar(20), @intErrNo)
+ ', @Param1=' + COALESCE(@Param1, 'NULL'),
....