SSISDB - Deploy project using T-SQL - sql-server

I am trying to deploy SSIS project into SSISDB using T-SQL. Say in case of any error while deploying, error messaged got logged into catalog.operation_messages view.
Now if I execute same deploy statement in Explicit SQL transaction and if any error occurs at time of deployment I am not able to find error logged into catalog.operation_message.
Ex.
BEGIN
BEGIN TRY
BEGIN TRAN TRAN1
Declare #folder_id bigint
EXEC SSISDB.catalog.create_folder #folder_name='test1', #folder_id=#folder_id OUTPUT
Select #folder_id
EXEC SSISDB.catalog.set_folder_description #folder_name='test1', #folder_description='test1'
--Deploy
DECLARE #ProjectBinary as varbinary(max)
DECLARE #operation_id as bigint
Set #ProjectBinary = (SELECT * FROM OPENROWSET(BULK 'C:\Test\MyProject.ispac', SINGLE_BLOB) as BinaryData)
Exec SSISDB.catalog.deploy_project #folder_name = 'test1', #project_name = 'ABC', #Project_Stream = #ProjectBinary, #operation_id = #operation_id out
COMMIT TRAN TRAN1
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE()
COMMIT TRAN TRAN1
END CATCH
END
This return me error message something like
Failed to deploy project. For more information, query the operation_messages view for the operation identifier '34704'.
But when I query view and try looking for same I am not able to find any message logged by this operation_Id, is it rollbacked? if yes by which process? how I can retain it?
Help me in understanding it.

Related

How to modify SQL Server Error Message

I have started a SQL Server locally on my computer. Now I am trying to find a way to modify error messages I get in SSMS.
Well you can do a TRY-CATCH. Something like the following:
SET NOCOUNT ON
CREATE TABLE #tmp(TestCol varchar(20))
INSERT INTO #tmp VALUES('test')
BEGIN TRY
INSERT INTO #tmp VALUES('testtesttesttesttesttest')
END TRY
BEGIN CATCH
DECLARE #nErrorNum INT;
SELECT #nErrorNum = ERROR_NUMBER()
IF #nErrorNum = 8152
BEGIN
RAISERROR('String is too long',10,1);
END
ELSE
THROW
END CATCH

MS-SQL Using TRANSACTION with an cursor and inside an stored procedure

Can anybody tell what is wrong with this stored procedure?
I want to use a transacation within an stored procedure but if I run this procedure I get the following error message: "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION"
I don't get it... I tried so many options with the BEGIN and COMMIT commands...
P.S. It doesn't matter what's inside the while loop, the error still raises.
Any ideas?
The Error raises if I use the query window inside SSMS.
USE db
GO
DECLARE #return_value int,
#str_return nvarchar(100)
EXEC #return_value = [dbo].[proc_xxxx]
#guid = 'xxxxxxxxxxxxxxxxx',
#str_return = #str_return OUTPUT
SELECT #str_return as N'#str_return'
SELECT 'Return Value' = #return_value
GO
Maybe this is the reason?
-- Declare Cursor
DECLARE xx_cursor CURSOR FOR
SELECT GUID
FROM TABLE;
BEGIN TRY
BEGIN TRAN
OPEN xx_cursor;
-- Run through
FETCH NEXT FROM xx_cursor INTO #guid_xx;
WHILE ##FETCH_STATUS = 0
BEGIN
--DO SOMETHING
FETCH NEXT FROM xx_cursor INTO #guid_xx;
END;
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
SET #str_return = 'Error'
END CATCH
CLOSE xx_cursor;
DEALLOCATE xx_cursor;

Error Handling in VBS third party program like SQL

I have to develop a WinCC Visual Basic Script management application. In this application I read an XML archive, and after that I put the information in a SQL database through a SQL INSERT query.
My problem is that I don't know how to do the error handling to view the SQL errors in VBScript MsgBox for example.
Activating the error handling with On Error Resume Next and after the evaluation of these errors with If Err.Number <> 0 Then ... the errors produced in SQL Server don't appear in VBScript.
If you want to get SQL Server error, You can use stored procedure with transaction to insert data into table:
create procedure dbo.InsertTable (
#param1 nvarchar(80)
,#param2 nvarchar(80)
,#error_text nvarchar(400) output)
as
begin
begin tran
begin try
insert into YourTable (column1, column2)
values (#param1, #param2)
end try
begin catch
set #error_text = error_message()
rollback
return
end catch
commit
end
Now You will get eventually error from the output parameter #error_text
declare #error_text nvarchar(400)
exec dbo.InsertTable 'Value1','Value2', #error_text output
select #error_text

SQL Job with TRY reports success on failure when inserting from remote SP

I've found a way to fail a SQL Scheduled Job (with severity 16) that does not report failure (and so does not send email notifications). I've fixed my immediate issue, but I want to know why there is a failure case that does not report as failure, and if there are any other surprising ways to miss notification.
I've set up two linked servers and am attempting to run an hourly scheduled SQL Job on one that queries the other. I found this morning that the code in the SP had not been running, but the history on the Job was reporting success. The Job's only step is EXEC _testSP. If I ran EXEC _testSP in a query window from SSMS, I received this error message:
Msg 0, Level 11, State 0, Line 0 A severe error occurred on the
current command. The results, if any, should be discarded.
The SP's contents are wrapped in TRY ... CATCH. If I remove the TRY ... CATCH, executing the SP gives up this error message:
Msg 213, Level 16, State 7, Line 1
Insert Error: Column name or number of supplied values does not match table definition.
This made sense. The remote table was referenced with a SELECT * FROM and some columns had been added to it. I've removed the asterix and the job runs fine now, but I want to make sure that all future exceptions get logged either by the job failure notification, or the CATCH block in _testSP. I don't understand why this one didn't get logged, and I hope that someone can explain it to me.
The job runs and fails and notifies just as I would expect when the TRY ... CATCH wrapping is removed, but we have some important things in the TRY ... CATCH that need to be kept.
This is not a duplicate of this related question. The Microsoft BOL for TRY...CATCH says that some exceptions cannot be caught by TRY...CATCH. It may be related, but what I've found is an exception that is not caught by the Scheduled Job agent.
Reproduceable example: (also try removing the TRY...CATCH wrapper and see the change)
USE [RemoteServer].[Database]
CREATE TABLE [Tally](
[ID] [int] IDENTITY(0,1) NOT NULL,
[ID2] [int] NOT NULL
) ON [PRIMARY]
GO
USE [LocalServer]
-- Setup procedure
CREATE PROCEDURE _testSP
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
-- Create destination temp table
CREATE TABLE #tempb (a int)
-- Insert into temp table from remote Tally table
DECLARE #query nvarchar(4000)
SELECT #query = '
SELECT TOP 5 *
FROM [Database].[dbo].Tally
'
INSERT INTO #tempb
EXEC [RemoteServer].[master].[dbo].sp_executesql #query
END TRY BEGIN CATCH
-- Log the exception
-- ...
-- Rethrow the exception
DECLARE #ErrorMessage nvarchar(max), #ErrorSeverity int, #ErrorState int;
SELECT
#ErrorMessage = 'Handled Exception: ' + ERROR_MESSAGE() + ' line ' + CAST(ERROR_LINE() as nvarchar(5)),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE();
RAISERROR (#ErrorMessage, #ErrorSeverity, #ErrorState);
END CATCH
END
GO
-- Setup job
DECLARE #database varchar(100)
SELECT #database = DB_Name()
EXEC msdb.dbo.sp_add_job
#job_name = '_testSPJob'
EXEC msdb.dbo.sp_add_jobstep
#job_name = '_testSPJob',
#step_name = '_testSPJob',
#subsystem = N'TSQL',
#command = 'EXEC _testSP',
#database_name = #database
EXEC msdb.dbo.sp_add_jobserver
#job_name = '_testSPJob',
#server_name = ##SERVERNAME
GO
-- Manual execution fails
EXEC _testSP
GO
-- Run job
EXEC msdb.dbo.sp_start_job
#job_name = '_testSPJob'
WAITFOR DELAY '00:00:02'
GO
-- Select job history
SELECT * FROM msdb.dbo.sysjobhistory
WHERE step_name = '_testSPJob'
ORDER BY run_date, run_time
GO
I really need to convince the bosses to get off SQL 2000. Here are my software versions. Perhaps this is fixed in later versions of SQL?
SSMS Version: 2012 (11.0.5058.0)
Local DB: SQL 2005 (9.0.5069)
Remote DB: SQL 2000 (8.0.760)
I think that what is happening is correct, because you're handdling an exception, so the job is not failling. A solution could be a log so when the exception y catch you insert a row with the error description.

SQL Server error logging from a Stored Procedure

Our application is Windows Service (native .EXE written in C++) that calls stored procedures in SQL Server. In most cases errors in stored procedures (in 90% of the cases these errors mean something was wrong in our business logic) are re-thrown as exception and caught by our service. They are then logged in Application Event Log on the computer where our service is running.
However, I now have a need to log some of the errors on the SQL Server itself within a stored procedure.
Following the paradigm we use for our service I think I can use xp_logevent to save error information in the event log.
Is this a recommended approach to log SQL Server errors?
FWIW I use SQL Server 2008
The How To
You can always use RAISEERROR() WITH LOG. Logs to both Windows Application log and the SQL error log.Please note that severity level is key here. There are some limitations and security considerations, but you get some other features also.
More details in BOL:
http://msdn.microsoft.com/en-us/library/ms178592.aspx
The Should you
My opinion is that you shouldn't log anything to SQL error log unless it's generated by SQL server itself. Multiple reasons:
If your IT or DBA uses log analyzer or any other tool, it may trip an alarm on an application issue, instead of the server issue (this is what they are trying to catch).
I never found parsing error logs enjoyable from within SQL server, and I'm not particularly in love with SSMS's way of doing it.
My suggestion
Use a generic logging stored procedure writing to some error log table. A very nice patter is
BEGIN TRY
...do your stuff
END TRY
BEGIN CATCH
get the ERROR_LINE(), ERROR_MESSAGE() and friends
execute generic logging procedure
END CATCH
As a bonus, you can use SSSB within the logging procedure to make it async and not impede the main logic flow
Here is a useful way I have found to keep track of SQL Server errors. First, create a table to store the errors:
CREATE TABLE utiliity.dbo.ProcedureLog
(
LogDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
DatabaseID INT,
ObjectID INT,
ProcedureName NVARCHAR(400),
ErrorLine INT,
ErrorMessage NVARCHAR(MAX),
AdditionalInfo NVARCHAR(MAX)
);
GO
CREATE CLUSTERED INDEX cx_LogDate ON dbo.utiliity.dbo.ProcedureLog(LogDate);
GO
Then create a stored procedure to call when the error occurs:
CREATE PROCEDURE sp_CallProcedureLog
#ObjectID INT,
#DatabaseID INT = NULL,
#AdditionalInfo NVARCHAR(MAX) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#ProcedureName NVARCHAR(400);
SELECT
#DatabaseID = COALESCE(#DatabaseID, DB_ID()),
#ProcedureName = COALESCE
(
QUOTENAME(DB_NAME(#DatabaseID)) + '.'
+ QUOTENAME(OBJECT_SCHEMA_NAME(#ObjectID, #DatabaseID))
+ '.' + QUOTENAME(OBJECT_NAME(#ObjectID, #DatabaseID)),
ERROR_PROCEDURE()
);
INSERT utiliity.dbo.ProcedureLog
(
DatabaseID,
ObjectID,
ProcedureName,
ErrorLine,
ErrorMessage,
AdditionalInfo
)
SELECT
#DatabaseID,
#ObjectID,
#ProcedureName,
ERROR_LINE(),
ERROR_MESSAGE(),
#AdditionalInfo;
END
GO
Finally, in your stored procedures where you want to record the errors:
BEGIN TRY
... execute SQL commands here
END TRY
BEGIN CATCH
DECLARE #msg NVARCHAR(MAX);
SET #msg = 'Something went horribly wrong. Error number = ' + ERROR_NUMBER();
EXEC utiliity.dbo.sp_CallProcedureLog
#ObjectID = ##PROCID,
#AdditionalInfo = #msg;
DECLARE #ErrorMessage NVARCHAR(MAX);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
SELECT
#ErrorMessage = ERROR_MESSAGE(),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE();
-- Use RAISERROR inside the CATCH block to return error
-- information about the original error that caused
-- execution to jump to the CATCH block.
RAISERROR (#ErrorMessage, -- Message text.
#ErrorSeverity, -- Severity.
#ErrorState -- State.
);
END CATCH
Here are my sources: http://www.mssqltips.com/sqlservertip/2003/simple-process-to-track-and-log-sql-server-stored-procedure-use/ and http://msdn.microsoft.com/en-us/library/ms178592(SQL.105).aspx. HTH.
You can call xp_logevent to log messages in the event log. But for logging exceptions it is better to use the RAISERROR () WITH LOG statement.
If you are concerned about performance you can pass the message through a SQL Server Service Broker queue and have an activation procedure log the messages in the eventlog.
The downside is that whoever has to find out the errors now needs permissions to get into the event log.
If you go with this, make sure your log has more size than the default 512K. Also set it to overwrite events as needed.
Also, the event log is not as fast as your SQL Server database so you may want to run a load test to figure out if it slows your application down.

Resources