Introduction
For newer .NET application deployment, probably you don't need to do this because Microsoft database project creates Dacpac makes lives easier for automated deployment. However, life isn't always that perfect and sometimes you have to work on legacy projects that are using incremental SQL scripts (usually ordered by date). It is painful for the DBA to execute 100+ SQLs in a huge deployment, the chance of human error is high. Even worse, you cannot change the standard when the project is big and has been running for ages. Also, there are Architects and DBAs have never heard about Dacpac, believe it or not.
Background
There are ways or scripts on stackoverflow.com that does the execution SQL part, but they don't return the results for troubleshooting, especially on production we need to have a report for artifact to make sure every script executed successfully. I have written this script years ago and I have been using this for legacy projects in the past years. It just happen today that I want to share it on CodeProject to help other people.
Credits go to the following two articles:
Using the Code
The SQL script is simple, it is self explanatory and there are 3 variables you need to configure:
Set @DBServerName = 'localhost'
Set @DBName = 'YourDatabaseName'
Set @SourceFolder = 'C:\Temp\DB_SERVER\SQL\'
To use the script, you have to create a "SQL" folder and put all your .sql files there. Then, launch SQL Manager to open the DbServer_DeployScript.sql, run it. That's it.
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
GO
RECONFIGURE
GO
Declare @DBServerName nVarchar(100)
Declare @DBName nVarchar(100)
Declare @SourceFolder nVarchar(250)
Declare @Command nVarchar(250)
DECLARE @CommandShellResultCode int
DECLARE @CommandShellOutputTable TABLE (Line NVARCHAR(512))
DECLARE @SingleLineOutput nvarChar(max)
DECLARE @sourceID int
DECLARE @sourceSqlFilename nvarchar(512)
DECLARE @sourceDepth int
DECLARE @sourceIsFile bit
Set @DBServerName = 'localhost'
Set @DBName = 'YourDatabaseName'
Set @SourceFolder = 'C:\Temp\DB_SERVER\SQL\'
IF OBJECT_ID('tempdb..#DirectoryTree') IS NOT NULL
DROP TABLE #DirectoryTree;
CREATE TABLE #DirectoryTree (
ID int IDENTITY(1,1)
,SubDirectory nvarchar(512)
,Depth int
,IsFile bit);
INSERT #DirectoryTree (SubDirectory,Depth,IsFile)
EXEC master.sys.xp_dirtree @SourceFolder,1,1;
IF OBJECT_ID('tempdb..#ResultSummary') IS NOT NULL
DROP TABLE #ResultSummary;
CREATE TABLE #ResultSummary (
SqlFilename nvarchar(100),
ResultCode nvarchar(100),
ResultOutput nvarchar(max)
);
DECLARE ScriptCursor CURSOR FOR
SELECT * FROM #DirectoryTree
WHERE Isfile = 1 AND RIGHT(SubDirectory,4) = '.sql'
ORDER BY SubDirectory asc;
OPEN ScriptCursor;
FETCH NEXT FROM ScriptCursor
INTO @sourceID, @sourceSqlFilename, @sourceDepth, @sourceIsFile
WHILE @@FETCH_STATUS = 0
BEGIN
Delete from @CommandShellOutputTable
Set @Command = 'sqlcmd -S ' + @DBServerName + ' -d ' +
_@DBName + ' -i ' + '"' +@SourceFolder + @sourceSqlFilename + '"'
print @Command
INSERT INTO @CommandShellOutputTable
EXEC @CommandShellResultCode= xp_cmdshell @Command
SELECT @SingleLineOutput = (SELECT STUFF((
SELECT ',' + line
FROM @CommandShellOutputTable
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, ''))
IF (@CommandShellResultCode = 0)
Insert INTO #ResultSummary(SqlFilename, ResultCode, ResultOutput)
Values (@sourceSqlFilename, 'xp_cmdshell Executed', @SingleLineOutput)
ELSE
Insert INTO #ResultSummary(SqlFilename, ResultCode, ResultOutput)
Values (@sourceSqlFilename, 'xp_cmdshell Failed', @SingleLineOutput)
FETCH NEXT FROM ScriptCursor
INTO @sourceID, @sourceSqlFilename, @sourceDepth, @sourceIsFile
END;
CLOSE ScriptCursor;
DEALLOCATE ScriptCursor;
Select SqlFilename, ResultCode, ISNULL(ResultOutput, 'SUCCESSFUL') _
as SqlcmdResult from #ResultSummary order by SqlFilename asc
GO
As I have another script DbServer_BackupScript.sql that does that backup, based on current time stamp. This is handy and very simple. Just to throw it in here in case you may want it. You need to modify the backup path and "YourDatabaseName
" in the script:
Declare @filename Varchar(100)
Declare @datetime Varchar(50)
Set @datetime = CONVERT(char(50), GetDate(),121)
Set @filename = (SELECT LTRIM(Replace(@datetime, ':','-')))
Set @filename = (SELECT RTRIM(Replace(@filename, '.','-')))
Set @filename = (SELECT RTRIM(Replace(@filename, ' ','_')))
Set @filename = 'C:\Backup\YourDatabaseName_' + @filename + '.bak'
select @filename
USE [YourDatabaseName];
BACKUP DATABASE [YourDatabaseName]
TO DISK = @filename
Script in Action
In this screenshot below, I have 3 SQL scripts with 1 stored procedure, 2 update scripts with one valid + one invalid. As you can see, you can easily see which one fails.
Hope you find this useful.
History
- 2015-03-05 - First published