All we need is an easy explanation of the problem, so here it is.
The script needs to test to see if a backup table already exists and stop if it does. This is to prevent overwriting a backup already created.
The following will stop further script execution (but not interpretation output). However, it does not set the exit code value. It needs to set the exit code value in order to support automation.
This needs to work even if the user is not sysadmin. Therefore, RAISEERROR() with a severity code > 18 and WITH LOG does not improve the situation.
The script needs to work in both sqlcmd.exe and SSMS on SQL Server as early as 2012.
IF EXISTS (SELECT 1 FROM BUDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TABLE_A') BEGIN PRINT 'ERROR: Table BUDB.dbo.TABLE_A already exists.' RAISERROR('ERROR: Will not create existing backup table.', 18, -1); SET NOEXEC ON; END IF EXISTS (SELECT 1 FROM BUDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TABLE_B') BEGIN PRINT 'ERROR: Table BUDB.dbo.TABLE_B already exists.' RAISERROR('ERROR: Will not create existing backup table.', 18, -1); SET NOEXEC ON; END
How to solve :
I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.
First, I’d rewrite the script to use the
TRY..CATCH construct instead of the
SET NO EXEC ON.
As per this recommendation by Erland Sommarskog
This is my version of the script used for testing:
SET XACT_ABORT ON BEGIN TRY DECLARE @DbName sysname = DB_NAME() IF (@DbName LIKE 'm%') BEGIN RAISERROR('ERROR: DbName starts with m', 16, -1); END SELECT @@VERSION /* test if script continues */ END TRY BEGIN CATCH ;THROW /* Needed to rethrow the error*/ END CATCH
As for the SQLCMD there are two parameters:
- -b = terminate batch job if there is an error
- -V = error_severity_level
by default only errors with severity greater than 10, but you can override that with the -V parameter.
Here’s a link to documentation
The sqlcmd execution could then look like this
sqlcmd -S localhost -d master -i "FullPath.sql" -b; $LASTEXITCODE
Did you try the -b switch of sqlcmd ?
Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂