I am trying to execute a script based on IF NOT EXISTS condition. But, the block within BEGIN and END gets executed even if IF NOT EXISTS returns 1. I cannot change statements within BEGIN and END blocks. How to handle this situation?
IF NOT EXISTS(SELECT 1 FROM [dbo].[UPGRADEHISTORY] WHERE SCRIPTNAME='001-MarkSubmitted.sql' AND RELEASENUMBER= '1') BEGIN IF NOT EXISTS(SELECT 1 FROM [dbo].[Action] WHERE Name='mark As Submitted') BEGIN SET IDENTITY_INSERT [dbo].[Action] ON INSERT INTO [dbo].[Action](Id,Name,CreatedBy,CreatedOn) VALUES (6,'mark As Submitted',1,getdate()) SET IDENTITY_INSERT [dbo].[Action] OFF END GO INSERT INTO [dbo].[StatusActionMapping](ArtifactType,StatusId,ActionId,RoleId) VALUES ('Report',11,6,1) GO INSERT INTO [dbo].[UpgradeHistory] ([ReleaseNumber],[ScriptNumber],[ScriptName],[ExecutionDate]) VALUES (1, (SELECT FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3') FROM UpgradeHistory WHERE ReleaseNumber= 1),'001-MarkSubmitted.sql',GETDATE()); END GO
Advertisement
Answer
As I mention in the comment, GO
is not a Transact-SQL operator, it’s interpreted by your IDE/CLI as a batch separator.SQL Server Utilities Statements – GO:
SQL Server provides commands that are not Transact-SQL statements, but are recognized by the sqlcmd and osql utilities and SQL Server Management Studio Code Editor. These commands can be used to facilitate the readability and execution of batches and scripts.
GO signals the end of a batch of Transact-SQL statements to the SQL Server utilities.
The answer is simply, remove the GO
s. There is no need for them here; it’s because they are there that you are getting the error because separating the statements into different batches makes no sense here. What you have would be equivalent to having the following 3 “files” and trying to run them independently:
File 1:
IF NOT EXISTS(SELECT 1 FROM [dbo].[UPGRADEHISTORY] WHERE SCRIPTNAME='001-MarkSubmitted.sql' AND RELEASENUMBER= '1') BEGIN IF NOT EXISTS(SELECT 1 FROM [dbo].[Action] WHERE Name='mark As Submitted') BEGIN SET IDENTITY_INSERT [dbo].[Action] ON INSERT INTO [dbo].[Action](Id,Name,CreatedBy,CreatedOn) VALUES (6,'mark As Submitted',1,getdate()) SET IDENTITY_INSERT [dbo].[Action] OFF END
Would error due to a BEGIN
with out END
.
File 2:
INSERT INTO [dbo].[StatusActionMapping](ArtifactType,StatusId,ActionId,RoleId) VALUES ('Report',11,6,1)
This would run fine.
File 3:
INSERT INTO [dbo].[UpgradeHistory] ([ReleaseNumber],[ScriptNumber],[ScriptName],[ExecutionDate]) VALUES (1, (SELECT FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3') FROM UpgradeHistory WHERE ReleaseNumber= 1),'001-MarkSubmitted.sql',GETDATE()); END
Would error due to an END
without a BEGIN
.
There’s nothing in your query that will causing a parsing error like you’re adding a new column to an existing table and reference it later in the batch, so there’s no need to separate the batches. Just remove the GO
s in the middle of your BEGIN...END
s and this works as you require:
IF NOT EXISTS (SELECT 1 FROM [dbo].[UPGRADEHISTORY] WHERE SCRIPTNAME = '001-MarkSubmitted.sql' AND RELEASENUMBER = '1') BEGIN IF NOT EXISTS (SELECT 1 FROM [dbo].[Action] WHERE Name = 'mark As Submitted') BEGIN SET IDENTITY_INSERT [dbo].[Action] ON; INSERT INTO [dbo].[Action] (Id, Name, CreatedBy, CreatedOn) VALUES (6, 'mark As Submitted', 1, GETDATE()); SET IDENTITY_INSERT [dbo].[Action] OFF; END; INSERT INTO [dbo].[StatusActionMapping] (ArtifactType, StatusId, ActionId, RoleId) VALUES ('Report', 11, 6, 1); INSERT INTO [dbo].[UpgradeHistory] ([ReleaseNumber], [ScriptNumber], [ScriptName], [ExecutionDate]) VALUES (1, (SELECT FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3') --This is a REALLY bad idea. Use an IDENTITY or SEQUENCE FROM UpgradeHistory WHERE ReleaseNumber = 1), '001-MarkSubmitted.sql', GETDATE()); END; GO
Also note my point on your final INSERT
. FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3')
is going to end up with race conditions. Use an IDENTITY
or SEQUENCE
.