TRY CATCH in SQL Server - sql-server

I am using SQL Server 2008. I have tried to execute the following:
BEGIN TRY
SELECT 1/0;
END TRY
BEGIN CATCH
PRINT 'ERROR'
END CATCH;
But I am getting the following error:
>Msg 170, Level 15, State 1, Line 1
Line 1: Incorrect syntax near 'TRY'.
Msg 156, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'END'.
Can any one tell me how execute try catch in SQL Server?

That is a completely valid statement for SQL Server 2005 and up, so I'd check your compatibility level using sp_dbcmptlevel (Transact-SQL):
exec sp_dbcmptlevel 'YourDatabaseName'
80 = SQL Server 2000
90 = SQL Server 2005
100 = SQL Server 2008
I think it will return 80 or lower, it seems that it doesn't know BEGIN TRY, only BEGIN. The BEGIN TRY was added in SQL Server 2005.

If you still have this error, the question becomes, have you put a BEGIN CATCH...END CATCH section in. If not, you get this error. If you have a BEGIN TRY...END TRY section with no T-SQL code in it, then it will also produce the error.
I don't think it's helpful people tell you that you're using SQL Server 2000. It is more likely a T-SQL coding issue as you tend to know what server you are running.

Begin try
Begin transaction
--------
--------
Commit transaction
End try
Begin catch
Rollback transaction
End catch
http://intquesans.blogspot.com/2011/05/how-we-can-use-try-catch-in-sql.html

Related

SQL Server - Handle deadlock with retries

I am going this brutal way to handle deadlocks by re-trying 5 times (using SQL Server 2008R2) and no error handling.
I know it is not delicate, but for the scope of it, can you find any flaws?
Thank you
WHILE #retry < 5
BEGIN
BEGIN TRY
INSERT available
SELECT 'x','y','z'
BREAK
END TRY
BEGIN CATCH
IF error_number() = 1205 AND #retry < 5
BEGIN
SELECT #retry = #retry + 1
WAITFOR DELAY '00:00:00.100'
ELSE
BREAK
END
END CATCH;
END
EDIT: I have edited the code following #Charlieface helpfull suggestions.
I have never used TRY/CATCH in SQL server code though. Also THROW is not supported in SQL Server 2008R2
Any suggestions appreciated.

Why SQL Server stored procedure selecting encrypted data into variable fails

Stored procedure that selects data from encrypted column (Always Encrypted) into variable fails with an error
Cannot continue the execution because the session is in the kill state
if XACT_ABORT is set to on.
Removing SET XACT_ABORT ON; line makes the stored procedure work perfectly, but it is unclear how it is related.
Completely removing variable also fixes an error.
Environment:
Microsoft SQL Server 2016 Enterprise (64-bit) Service Pack 2 with CU2 (13.0.5153.0): latest build at the moment.
Microsoft Windows NT 6.3 (15063)
Stored procedure:
CREATE PROCEDURE [SomeStoredProcedure]
WITH EXECUTE AS OWNER
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
DECLARE #EncryptedValue VARBINARY(4096);
SELECT TOP 1
#EncryptedValue = [someencryptedcolumn]
FROM
[sometable];
SELECT #EncryptedValue
RETURN 0;
END;
Table declaration:
CREATE TABLE [sometable]
(
[someencryptedcolumn] [varbinary](4096)
ENCRYPTED WITH
(
COLUMN_ENCRYPTION_KEY = [CEK1],
ENCRYPTION_TYPE = Randomized,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
)
NULL
)
Sample data:
INSERT INTO [sometable] ([someencryptedcolumn])
VALUES (NULL)
Call the stored procedure:
EXEC [SomeStoredProcedure];
Error:
Msg 596, Level 21, State 1, Line 29
Cannot continue the execution because the session is in the kill state.
Msg 0, Level 20, State 0, Line 29
A severe error occurred on the current command. The results, if any, should be discarded.
I found no references on how XACT_ABORT and Always Encrypted related.
I also checked for SQL Server logs but found no additional information on the issue.
Update:
Link to the registered SQL Server bug
This is a bug in the product. You should first try installing the latest SP/CU to see if it has already been fixed and if not report it to Microsoft.
I can also reproduce this on SQL Server 2017 RTM. I haven't tried installing the latest CU to see if that improves things.
It isn't specific to XACT_ABORT. You also see the same with other set options. Such as
SET DATEFIRST 5
SET ANSI_NULLS OFF.
When these are present it ends up calling sqllang.dll!CEnvColEncryptionKey::XretSchemaChanged twice and the second time around it ends up trying to dereference a null pointer and fails with an Access violation reading location 0x0000000000000000.
The call stack when the error is thrown (by SELECT #EncryptedValue) is as follows.

RAISERROR Syntax error in SQL Server 2014

I'm working on migrating SQL Server 2008 R2 database to SQL Server 2014. Having trouble with the following trigger. Looks like something with RAISEERROR is not supported in newer version.
ALTER TRIGGER [dbo].[Route_ITrig]
ON [dbo].[Route]
FOR INSERT AS
/*
* PREVENT NULL VALUES IN 'RouteName'
*/
IF (SELECT Count(*) FROM inserted WHERE RouteName IS NULL) > 0
BEGIN
RAISERROR 44444 'Field ''RouteName'' cannot contain a null value.'
ROLLBACK TRANSACTION
END
This is the error I'm getting
Msg 102, Level 15, State 1, Procedure Route_ITrig, Line 15
Incorrect syntax near '44444'
This is a SQL function, hence all required variables must be passed in brackets, as follows:
RAISERROR(44444, 'Field ', 'RouteName', ' cannot contain a null value.')

Stop Script Execution if USE [database] Fails in SQL Server

Typically in a SQL Server script I will have a USE [database] statement at the start. This would be for a Schema Table creation script for example.
The script is assuming that the database already exists. However, to prevent accidentally running the script against a master database, I just want the script to terminate execution.
So error checking and try...catch does not work.
Error Check
USE [MYDATABASE]
IF ##ERROR <> 0
BEGIN
RAISERROR ('Cannot find database so skipping script creation', 1, 1);
GOTO AbortScript
END
...
AbortScript:
PRINT 'Aborted!'
Try Catch
BEGIN TRY
USE [MYDATABASE]
PRINT 'xxxx'
END TRY
BEGIN CATCH
PRINT 'OOps Errored'
END CATCH
Can you trap these errors? I am currently using SQL Server 2008 R2.
Check if the database exists first:
IF (NOT EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = 'mydatabase'))
BEGIN
RAISERROR ('Cannot find database so skipping script creation', 1, 1);
GOTO AbortScript
END;
USE [MYDATABASE]
I've been trying to abort a large SQL script that includes many batches (marked with "GO"). Unfortunately you can't use a GOTO block, IF block, or TRY-CATCH to skip multiple batches, but you can turn off command execution, which has the same effect.
IF EXISTS (SELECT 1 FROM sys.tables WHERE name = 'MyTable')
SET NOEXEC ON
(Don't forget to SET NOEXEC OFF at the end of your script)
Detailed reference here.

How do I get SQL Server Management Studio to stop processing on an error?

This seems like an incredibly dumb question to have to ask, but how do I get SQL Server Management Studio to stop processing a SQL script when it encounters an error?
I have a long script and if there is an error at the start SSMS reports it and then blindly carries on, screwing up things even more. I can't use transactions because the script creates several databases and they can't go in a transaction. It is the database creation that sometimes fails.
Toad for SQL Server will pause at the first error it encounters and ask if you want to stop or continue. This is the behaviour I'm looking for. Does it exist in SSMS?
I am not asking, "How do I write or modify a script so that it stops on an error?" I'm not interested in modifying my script to make this happen, I just want SSMS to stop on an error. Toad for SQL Server does exactly this and that is the behaviour I want. This is also not a duplicate of 659188 because that relates to modifying the script to stop SSMS.
Short answer: You can't.
Thanks to those that provided workarounds, but it seems that SSMS itself can not be set to pause or stop on an error in the same way that Toad for SQL Server can.
consider using the command line program 'sqlcmd' that comes with SQL Server, with the -b and the -V options set. -b will cause sqlcmd to quit when it hits an error. -V controls the severity level that is considered to be an error.
ApexSQL Script generates batch scripts in exactly the manner you want. As an example:
--Script Header
begin transaction
go
{Statement #1}
go
--Standard Post-Statement Block
if ##error <> 0 or ##trancount = 0 begin
if ##trancount > 0 rollback transaction
set noexec on
end
go
{Statement #2}
go
--Standard Post-Statement Block
if ##error <> 0 or ##trancount = 0 begin
if ##trancount > 0 rollback transaction
set noexec on
end
go
--Script Footer
if ##trancount > 0 commit transaction
go
set noexec off
go
11 years later SSMS still doesn't have this feature...
BUT! You can enable SQLCMD mode (Menu/Query/SQLCMD Mode) and then in text editor you can define this option:
:ON ERROR EXIT
before your t-sql script. Now it will stop execution on error.
You need to wrap your SQL Statements inside a Transaction.
BEGIN TRANSACTION
/* run all your SQL statements */
COMMIT TRANSACTION
If there's an error inside the begin/end transaction, all statements will be rolled back.
EDIT: Wrapping inside inside begin/end transaction, will prevent the statements from getting committed to the database, but not stop it at that point. You need to additionally wrap it inside a try/catch block as follows:
BEGIN TRY
BEGIN TRANSACTION
/* run all your SQL statements */
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
Wow. That's kinda rubbish isn't it? I use SQL-Workbench which, like Toad for SQL Server, handles this easily. Unlike Toad for SQL Server though, it's free.
I'm astonished that such fundamental functionality isn't part of the standard tool.
would using a try catch block help here. On error the try will be exited, implement error handling in the catch
http://msdn.microsoft.com/en-us/library/ms179296.aspx
There are a few more work-arounds mentioned here:
SQL Server - stop or break execution of a SQL script
and
SQL Server: How to abort a series of batches in Query Analyzer?
(raiseerror 20 with log, set noexec on, sqlcmd mode :on error exit, etc.)
If you can't put your script into a stored procedure and use the return statement to exit on error, the solution provided by #Justice might be your best bet. Everyone else is missing the point - you can't return from a script, even if you use transactions or even if you raiserror. SSMS will just execute the next thing anyway, even if set xact abort is on.
If you can convert your script to a stored procedure, then you can just return from it when you detect an error.

Resources