create a try and catch inside loop - sql

I want to loop though the "RPT_ID = 245 " from 1 to 245 and inside the try and catch the invalid query statements so that the invalid queries will be caught.
The query column is a dynamic sql statement created for reports.
alter PROCEDURE usp_ExampleProc
AS
declare
#vsql2 as nvarchar(max)
,#vquery2 as nvarchar(max)
,#value as nvarchar(max)
,#value2 as nvarchar(max)
,#Q1 as nvarchar(max)
,#RP_NUM as nvarchar(max)
,#count as int
select #count = count(*) from saved_reports
while #count > 0
begin
select #q1 = query,#RP_NUM =RPT_ID from SAVED_REPORTS WHERE RPT_ID = #count
exec sys.sp_executesql #q1
BEGIN TRY
EXECUTE usp_ExampleProc;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
set #count = #count - 1
end

use
EXECUTE usp_GetErrorInfo;
in your catch statement.
see http://technet.microsoft.com/en-us/library/ms175976.aspx

Related

Require to select all error message from sp in sql server

ALTER PROC usp_test
AS
BEGIN
DECLARE #errorMsg NVARCHAR(MAX) = ''
CREATE TABLE #tmp (id TINYINT)
INSERT INTO #tmp (id)
SELECT 1666555666666
SET #errorMsg =#errorMsg + ISNULL(ERROR_MESSAGE(),'')
INSERT INTO #tmp (id)
SELECT 1
SET #errorMsg =#errorMsg + ISNULL(ERROR_MESSAGE(),'')
INSERT INTO #tmp (id)
SELECT 'a'
SET #errorMsg =#errorMsg + ISNULL(ERROR_MESSAGE(),'')
SELECT #errorMsg
END
Above is my sp and its giving two error and i need to select all error message.
Please guide me for same.
Note: Write now its giving two error but it can be of any number.
This is just sample sp
Try this :
ALTER PROC usp_test
AS
BEGIN TRAN
DECLARE #errorMsg NVARCHAR(MAX) = ''
CREATE TABLE #tmp (id TINYINT)
BEGIN TRY
INSERT INTO #tmp (id)
SELECT 1666555666666
END TRY
BEGIN CATCH
SET #errorMsg =#errorMsg + ISNULL(' - '+ERROR_MESSAGE(),'')
END CATCH
BEGIN TRY
INSERT INTO #tmp (id)
SELECT 1
END TRY
BEGIN CATCH
SET #errorMsg =#errorMsg +ISNULL(' - '+ ERROR_MESSAGE(),'')
END CATCH
BEGIN TRY
INSERT INTO #tmp (id)
SELECT 'a'
END TRY
BEGIN CATCH
SET #errorMsg =#errorMsg +ISNULL(' - '+ ERROR_MESSAGE(),'')
END CATCH
IF #errorMsg=''
COMMIT TRAN
IF #errorMsg<>''
BEGIN
SELECT #errorMsg
ROLLBACK TRAN
END
GO
BEGIN
DECLARE #msg VARCHAR(max);
BEGIN try
SELECT 1 / 0;
END try
BEGIN catch
CREATE TABLE #temp
(
err VARCHAR(100)
);
INSERT INTO #temp
SELECT Error_message() AS ErrorMessage;
SET #msg= (SELECT err
FROM #temp)
PRINT #msg
END catch
END

SQL Trigger - Commit Update and CATCH Block of Procedure

I have a trigger on a table that executes a stored procedure. The executed stored procedure has a TRY/CATCH, so that if there is an error, a row is inserted into a log table.
When the stored procedure fails, I'm getting the following error:
The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.
How do I make it so the update get committed and the CATCH in the stored procedure is also executed? If I add:
IF ##TRANCOUNT > 0
ROLLBACK TRAN
to the stored procedure, then I get the following error:
The transaction ended in the trigger. The batch has been aborted.
Trigger:
ALTER TRIGGER [dbo].[trigger123] ON [dbo].[tbl321]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE (status)
BEGIN
IF EXISTS (--some condition)
BEGIN
EXEC SProc
END
END
END
SProc:
ALTER PROCEDURE [dbo].[SProc ]
AS
BEGIN
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
BEGIN TRY
select #sql = '
declare #error1 varchar(255),
#error2 varchar(255),
#error3 varchar(255)
Exec SomeDB.DBO.ConfirmStatus ''A10594'',#error1 output,#error2 output,#error3 output
if ISNULL(#error1,0) <> 0
begin
set #error1 = ISNULL(#error2,'''') + '' '' + ISNULL(#error3,'''') + '' '' + ISNULL(#error1,0)
RAISERROR (#error1, 16, 1)
end'
from jobs j
exec(#sql) at [linked_server]
update status
set status_prev = 1
END TRY
BEGIN CATCH
SELECT
#ErrorMessage = ERROR_MESSAGE(),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE()
INSERT INTO error_log (error_datetime, [error_message])
SELECT
GETDATE(),
'Msg: ' + ISNULL(CONVERT(VARCHAR, ERROR_NUMBER()), 'N/A') + ', Level: ' + ISNULL(CONVERT(VARCHAR, #ErrorSeverity), 'N/A') + ', Line: ' + ISNULL(CONVERT(VARCHAR, ERROR_LINE()), 'N/A') + ', Error: ' + ISNULL(#ErrorMessage, 'N/A')
END CATCH
END
I was able to modify my stored procedure to not use a try/catch. This gets me what I need.
ALTER PROCEDURE [dbo].[SProc ]
AS
BEGIN
DECLARE #error table (error1 varchar(255))
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
BEGIN TRY
select #sql = '
declare #error1 varchar(255),
#error2 varchar(255),
#error3 varchar(255)
Exec SomeDB.DBO.ConfirmStatus ''A10594'',#error1 output,#error2 output,#error3 output
if ISNULL(#error1,0) <> 0
begin
set #error1 = ISNULL(#error2,'''') + '' '' + ISNULL(#error3,'''') + '' '' + ISNULL(#error1,0)
select #error1
end'
from jobs j
insert into #error
exec(#sql) at [linked_server]
if exists (select top 1 error1 from #error)
begin
INSERT INTO error_log (error_datetime, [error_message])
SELECT
GETDATE(),
(select top 1 error1 from #error)
else
update status
set status_prev = 1
END

EXEC sp_testlinkedserver over multiple Linked Servers

I'm trying to get error messages over all my Linked Servers.
So I've three Linked Servers:
IT_DATA
193.0.1
Monitoring_Data
I know that executing the following query I will get the info that I need to one Linked Server:
BEGIN TRY
EXEC sp_testlinkedserver N'193.0.1';
EXEC sp_executesql N'SELECT * FROM OPENQUERY([193.0.1], ''SELECT 1 AS c;'');';
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH;
PRINT 'We got past the Catch block!';
But I'm trying to create a loop to exec the SP to all of my Linked Servers:
DECLARE #Linked_Server varchar(50)
SET #Linked_Server = '193.0.1'
BEGIN TRY
EXEC sp_testlinkedserver N'193.0.1';
EXEC sp_executesql N'SELECT * FROM OPENQUERY([193.0.1], ''SELECT 1 AS c;'');';
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH;
PRINT 'We got past the Catch block!';
But I don't know how can I create a loop to get the information of all the Linked Servers into one table.
Anyone have an closer example?
Thanks!
I don't like using cursors but in this case... Try this:
create table dbo.LinkedServer (
LSName nvarchar(128)
, ErrorNumber int
, ErrorMessage nvarchar(4000)
);
DECLARE #Linked_Server nvarchar(128)
, #SQLString nvarchar(max);
declare crsLinkedServers cursor
for
select
s.name
from sys.servers s
where s.is_linked = 1;
open crsLinkedServers;
fetch next from crsLinkedServers
into #Linked_Server;
while ##fetch_status = 0
begin
BEGIN try
set #SQLString = N'SELECT * FROM OPENQUERY([' + #Linked_Server + '], ''SELECT 1 AS c;'');'
EXEC sp_testlinkedserver #Linked_Server;
EXEC sp_executesql #SQLString;
END TRY
BEGIN catch
insert into dbo.LinkedServer (LSName, ErrorNumber, ErrorMessage)
SELECT #Linked_Server, error_number(), error_message();
END CATCH;
fetch next from crsLinkedServers
into #Linked_Server;
end
close crsLinkedServers;
deallocate crsLinkedServers;
select
*
from dbo.LinkedServer;
drop table dbo.LinkedServer;

Finding out the type of value passed is select statement or csv without using SQL predefined keyword

Please provide help in this created procedure which when executes returns result as the value passed to parameter it is csv or it is select.
Here I used select in like statement to find out what value is passed. there is any way in which without using any sql keyword I can identified whether passed parameter value is csv or it is select
Create procedure TypeOfvalue
(#abc varchar(max))
as
begin
IF (#abc like '%select%')
begin
Print 'It is select'
End
Else
Begin
Print 'It is CSV'
End
First:
Declare #abc varchar(max)
set #abc='1'
execute TypeOfvalue #abc
Output: "It is CSV"
Second:
Declare #abc varchar(max)
set #abc='select * from tbl1'
execute TypeOfvalue #abc
Output: "It is a Select"
You can use the PARSEONLY in combination with NOEXEC options for this. See this code example:
CREATE PROCEDURE #TypeOfvalue (#code nvarchar(max)) AS
BEGIN
DECLARE #result int
BEGIN TRY
EXEC(N'SET PARSEONLY ON;SET NOEXEC ON;'+#code+N';SET NOEXEC OFF;SET PARSEONLY OFF;')
PRINT(N'Statement')
SET #result = 1
END TRY
BEGIN CATCH
PRINT(N'CSV')
SET #result = 2
END CATCH
RETURN #result
END
GO
DECLARE #returnCode int
EXECUTE #returnCode = #TypeOfvalue #code = N'abc;'
SELECT #returnCode as returned -- 2 (CSV)
EXECUTE #returnCode = #TypeOfvalue #code = N'SELECT * FROM sys.all_objects'
SELECT #returnCode as returned
DROP PROCEDURE #TypeOfvalue -- 1 (SELECT)
Source
CREATE PROC TestProc
#SQL NVARCHAR(MAX)
AS
BEGIN
IF EXists (
SELECT 1 FROM sys.dm_exec_describe_first_result_set(#SQL, NULL, 0)
WHERE error_message IS NOT NULL
AND error_number IS NOT NULL
AND error_severity IS NOT NULL
AND error_state IS NOT NULL
AND error_type IS NOT NULL
AND error_type_desc IS NOT NULL )
BEGIN
Print 'It is CSV'
END
ELSE
BEGIN
Print 'It is Select'
END
END
GO
Note that this is check the validation it means that a valid SELECT statement not any input that have a SELECT keyword.
And also this will say input is valid for other valid statements like UPDATE, INSERT and etc.

SQL 2005 try/catch block never reaches 'catch' despte bogus data tests

OK, I am not that experienced with SQL 2005 error handling and am
learning my way around try/catch statements.
I have written the below procedure but no matter what I pass to it,
there is never any data in my ErrorLog table. I have passed all INT
values, all datetime values, or data strings that are not in the DB
and get '0 rows effected' with nothing reported in ErrorLog. It is
as if the CATCH statement is never reached (for what it is worth, I
have also tried commenting out the validation at the top).
Any ideas what I am doing wrong? Thanks.
ALTER PROCEDURE [dbo].[aspnet_Membership_UpdateLastActivityDate]
#UserId nvarchar(256),
#UserName nvarchar(256),
#LastActivityDate datetime,
#ApplicationName nvarchar(256)
AS
DECLARE #Today DATETIME
DECLARE #MSG VARCHAR(255)
DECLARE #Severity INT
DECLARE #ErrorCode INT
BEGIN
SET XACT_ABORT ON -- (I have also tried it without XACT_ABORT. No difference)
BEGIN TRY
SET #ErrorCode = 0
SELECT #Today = GetDate()
IF (#UserId IS NULL)
RETURN(1)
IF (#UserName IS NULL)
RETURN(1)
IF (#LastActivityDate IS NULL)
RETURN(1)
BEGIN TRAN
UPDATE dbo.aspnet_Users WITH (ROWLOCK)
SET LastActivityDate = #LastActivityDate
FROM dbo.aspnet_Users u
INNER JOIN dbo.aspnet_Applications a
ON u.ApplicationId = a.ApplicationId
WHERE u.UserName = #UserName
AND u.UserId = #UserId
AND a.ApplicationName = #ApplicationName
COMMIT TRAN
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN
SET #ErrorCode = Error_Number()
SET #Severity = Error_Severity()
SET #MSG = 'An error was thrown: '
+ 'Error(' + #ErrorCode + '):' + ERROR_MESSAGE()
+ ' Severity = ' + ERROR_SEVERITY()
+ ' State = ' + ERROR_STATE()
+ ' Procedure = ' + ERROR_PROCEDURE()
+ ' Line Number = ' + ERROR_LINE()
INSERT INTO [dbo].[ErrorLog]([errornum], [errortype], [errormsg],[errorsource], [errordate])
VALUES (#ErrorCode, 'E', #MSG, Error_Procedure(), #Today)
RAISERROR(#MSG, #Severity, 2)
END CATCH
END
RETURN #ErrorCode
It has been awhile since I've done a lot with SQL Error handling but I don't see any place that is likely to generate an error. Are you expecting the "Return" statements to be "Caught"? That isn't going to happen...they'll just return from the function. You'll need to raise an error, not trigger a Return.
Agreed with #Mark. Try changing this:
IF (#UserId IS NULL)
RETURN(1)
To this:
IF (#UserId IS NULL)
BEGIN
RAISERROR('No UserID was passed in.', 11, 1);
RETURN 1;
END
Also see this article for a fantastic error handling primer by Erland Sommarskog:
http://www.sommarskog.se/error_handling_2005.html