I would like to ignore post deployment scripts after it has been deployed. How do you archive/remove a branch specific post deployment script after it has been deployed on production environment in SSDT? Are there any best practices around?
1 Answers
What I used to do is to create log table and store all the executed scripts. This is the table structure:
CREATE TABLE dbo.publish_script_logs
(
script_name_id VARCHAR(255) NOT NULL
, database_name VARCHAR(255) NOT NULL
, execution_time DATETIME2(7) NOT NULL
);
Then we created following scripts folder structure:
one_time_scripts
initial_data_insert.sql
...
postscript_all_together.sql
prescript_all_together.sql
...
Script.PostDeployment1.sql
Script.PreDeployment1.sql
where initial_data_insert.sql
is your needed script that is supposed to be executed on environment just once and pre\postscript_all_together.sql
are the scripts where all these scripts are collected together. Build = None must be set for all of these scripts. There is limitation - GO statement separator is not allowed in "one time scripts".
Now this is what will these 2 scripts will have inside for single script:
:SETVAR ScriptNameId ".\initial_data_insert"
GO
IF NOT EXISTS ( SELECT *
FROM [dbo].[publish_script_logs]
WHERE [Script_Name_Id] = '$(ScriptNameId)'
AND [database_name] = DB_NAME()
)
BEGIN
BEGIN TRY
:r $(ScriptNameId)".SQL"
INSERT INTO [dbo].[publish_script_logs]
VALUES ( '$(ScriptNameId)', DB_NAME() ,GETDATE() );
END TRY
BEGIN CATCH
DECLARE @err VARCHAR(MAX) = ERROR_MESSAGE();
DECLARE @msg VARCHAR(MAX) = 'One time script $(ScriptNameId).sql failed ' + @err;
RAISERROR (@msg, 16, 1);
END CATCH
END;
GO
And finally in the Script.PostDeployment1.sql
and Script.PreDeployment1.sql
files you'll have:
:r .\one_time_scripts\postscript_all_together.sql
and
:r .\one_time_scripts\prescript_all_together.sql

- 5,447
- 5
- 44
- 88
-
So - if I wanted to have a series of "run-once" type scripts, I'd create wrappers for all of them something like this? Considering it more for cases where we have data migrations that we don't want to repeat. Does it still drop all of that code into your post-deploy script whether or not it needs to run again? – Peter Schott Aug 23 '19 at 22:01
-
I'm not sure that I fully understood you. You need to create such wrapper for every script you want to execute just once. It will store the filename in the database log table after the execution. Next time this script will be skipped as there will be entry in the table. All of these wrappers will be added to the final script anyway. We have powershell script that calls database and depending on the log table, delete this wrappers from the script. It makes it easier to review the script before deployment. – Dmitrij Kultasev Aug 24 '19 at 05:38