Require to select all error message from sp in sql server - sql

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

Related

Raiserror Proc if table is empty

can anyone help me with raiserror in stored procedure.
My Proc
Alter Proc Proc_Test
as
begin
declare #runID int;
set #runID =
(
select max(isnull([RunID],0)) + 1
from [dbo].[Stored_Proc_Test]);
insert into [dbo].[Stored_Proc_Test]
( RunID,
ServerName,
DatabaseName,
ExecutionUser,
ProcName,
StartDate)
select #runID,
##SERVERNAME,
DB_NAME(),
SYSTEM_USER,
OBJECT_NAME(##procid) as ProcName,
GETDATE () as StartDate;
declare #Countrow int
set #Countrow= (select count(*) from [dbo].[Athletes] )
begin try
truncate table [dbo].[Athletes]
insert into [dbo].[Athletes]
select * from [dbo].[Athletes_Stored]
delete from [dbo].[Athletes_History]
where 1 = 1
insert into [dbo].[Athletes_History]
select * from [dbo].[Athletes]
update [dbo].[Stored_Proc_Test]
set EndDate = getdate (),
RowsAffectec = ##ROWCOUNT,
TaskStatus = 'Complete successfully'
where RunID = #runID
end try
begin catch
update [dbo].[Stored_Proc_Test]
set Runcomments = 'Error on line' + Cast(Error_Line() as varchar(10)),
TaskStatus = 'Failed',
ErrorMsg = Cast(Error_Number() as varchar(20)) + ': '+ ERROR_MESSAGE()
where RunID = #runID
end catch;
end
what I'm trying to do is if table [dbo].[Athletes] is EMPTY stop running the SP and throw message "EMPTY SOURCE". If table is not empty keep running the SP.
Thank you

Trigger to block insert into SQL Server

I have a requirement to prevent insert into table using after insert based on certain condition. When I am calling insert statement directly, it is executing perfectly without any problem. Whereas when am using procedure for insert statement with transaction scope, I am getting this error
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
My code:
create table test
(
id int ,
name varchar(10)
)
create table test1
(
id int ,
name varchar(10)
)
ALTER PROCEDURE test_insert
#id INT, #name NVARCHAR(10)
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO test1 (id, name)
VALUES (#id, #name)
INSERT INTO test (id, name)
VALUES (#id, #name)
COMMIT
END TRY
BEGIN CATCH
ROLLBACK;
DECLARE #errormsg NVARCHAR(MAX)
SELECT #errormsg = ERROR_MESSAGE();
THROW 500001, #errormsg, 1;
END CATCH
end
ALTER TRIGGER TRG_test
ON dbo.test
AFTER INSERT AS
BEGIN
DECLARE #idNum INT
SELECT #idNum = id FROM inserted
IF #idNum = 1
BEGIN
RAISERROR('error', 1,1);
ROLLBACK TRANSACTION
RETURN
END
END
Please let me know if am missing anything
Remove the ROLLBACK TRANSACTION inside the Trigger, remember that DML statements within the trigger will use the transaction context of the statement that fired the trigger, in this case, it would be covered by:
Your SP ==>
BEGIN TRANSACTION
--Fired the trigger and is involved by the same Transaction from the SP
insert into test1 (id,name) values(#id,#name)
insert into test (id,name) values(#id,#name)
COMMIT
Remove the ROLLBACK from the trigger and raise and error with severity 11 or higher so that the stored procedure CATCH block is entered. The code below also uses the simplified version of THROW to reraise the trigger error instead of throwing a new one and uses EXISTS to handle multi-row inserts.
alter proc test_insert #id int, #name nvarchar(10)
as
begin
BEGIN TRY
BEGIN TRANSACTION
insert into test1 (id,name) values(#id,#name)
insert into test (id,name) values(#id,#name)
COMMIT
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH
end
GO
alter TRIGGER TRG_test
ON dbo.test
AFTER INSERT AS
BEGIN
if EXISTS(select 1 from inserted WHERE id = 1)
begin
RAISERROR('error', 16,1);
RETURN
end
END
GO
From my understanding,
alter TRIGGER TRG_test
ON dbo.test
instead of insert as --- Trigger type is changed. Trigged before insert
BEGIN
declare #idNum int
select #idNum = id from inserted
if #idNum <> 1 ------ Condition is changed
begin
/* Do what you want.*/
RETURN
end
END
update 1:
create table test(
id int ,
name varchar(10)
)
create table test11(
id int ,
name varchar(10)
)
alter proc test_insert #id int, #name nvarchar(10)
as
begin
BEGIN TRY
BEGIN TRANSACTION
insert into test11(id,name) values(#id,#name)
insert into test (id,name) values(#id,#name)
COMMIT
END TRY
BEGIN CATCH
ROLLBACK;
declare #errormsg nvarchar(max)
select #errormsg=ERROR_MESSAGE();
THROW 500001, #errormsg, 1;
END CATCH
end
alter TRIGGER TRG_test
ON dbo.test
instead of insert as --- Trigger type is changed. Trigged before insert
BEGIN
declare #idNum int, #name int
select #idNum = id, #name=name from inserted
if #idNum <> 1 ------ Condition is changed
begin
insert into test (id,name) values(#idNum,#name)
end
else begin
print 'You insert invalid value 1'
end
END
test_insert 1, 2 -- error will be arised.
select * from test
select * from test11
test_insert 2, 2 -- insertion is occurs.
select * from test
select * from test11

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;

create a try and catch inside loop

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