Click here to Skip to main content
15,888,527 members
Articles / DevOps / Deployment
Tip/Trick

Run All .sql Files in a Directory for Deployment

Rate me:
Please Sign up or sign in to vote.
3.58/5 (5 votes)
5 Mar 2015CPOL2 min read 33.9K   434   9   2
Run all .sql files in a directory with results returned showing execution being successful or failure

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:

SQL
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.

SQL
------------------------------------------------------------------------------------
-- Execute all .SQL scripts one by one (order by filename in ascending order)
-- Written by Rini Boo 

-- Usage:  Run this in SQL Manager
-- Put all your .SQL scripts in a folder and it will run all of them automatically 
-- with Results showing if you encounter any error

-- References: 
--
-- Ref: List All files in a folder
-- http://www.patrickkeisler.com/2012/11/how-to-use-xpdirtree-to-list-all-files.html
--
-- Ref: Concat multiple rows into single variable
-- http://stackoverflow.com/questions/18102283/how-to-concat-many-rows-into-one-string-in-sql-server-2008
	
------------------------------------------------------------------------------------

   
------------------------------------------------------------------------------------
-- Configure current user to use xp_cmdshell
------------------------------------------------------------------------------------

-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO

------------------------------------------------------------------------------------
-- Define the variables
------------------------------------------------------------------------------------

-- General variables 
Declare @DBServerName nVarchar(100)
Declare @DBName nVarchar(100)
Declare @SourceFolder nVarchar(250)
Declare @Command nVarchar(250)
DECLARE @CommandShellResultCode int	-- Result code is not really useful
DECLARE @CommandShellOutputTable TABLE (Line NVARCHAR(512)) -- Output is more useful for exception
DECLARE @SingleLineOutput nvarChar(max)

-- Single variables for cursor to use
DECLARE @sourceID int
DECLARE @sourceSqlFilename nvarchar(512)
DECLARE @sourceDepth int
DECLARE @sourceIsFile bit

-- Set the variables  
Set @DBServerName = 'localhost'
Set @DBName = 'YourDatabaseName'
Set @SourceFolder = 'C:\Temp\DB_SERVER\SQL\'

------------------------------------------------------------------------------------
-- Create a temp table and get the list of files from the folder
------------------------------------------------------------------------------------


-- Get all the SQL from the path
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;


--SELECT * FROM #DirectoryTree
--WHERE IsFile = 1 AND RIGHT(SubDirectory,4) = '.sql'
--ORDER BY subdirectory asc


------------------------------------------------------------------------------------
-- Exec one by one 
------------------------------------------------------------------------------------

IF OBJECT_ID('tempdb..#ResultSummary') IS NOT NULL
      DROP TABLE #ResultSummary;

-- Create a result table for reference after sql being executed
CREATE TABLE #ResultSummary (
	   SqlFilename nvarchar(100),
	   ResultCode nvarchar(100),  -- for xp_cmdshell
	   ResultOutput nvarchar(max)   -- more for sqlcmd exception 
		);

-- Loop thro each SQL using cursor

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
 
-- Note: first one already been fetched
        
WHILE @@FETCH_STATUS = 0
   BEGIN
		-- PRINT 'Debug' + @sourceSqlFilename
     
		-- Clean up output table
        Delete from @CommandShellOutputTable
     
		-- Construct the command and execute the query           
		Set @Command = 'sqlcmd -S ' + @DBServerName + ' -d  ' + 
		_@DBName + ' -i ' + '"' +@SourceFolder + @sourceSqlFilename + '"'   
		print @Command
		
		-- Get the output and execute the command (with multiple lines output)
		INSERT INTO @CommandShellOutputTable
		EXEC @CommandShellResultCode= xp_cmdshell  @Command 
		
		
		---- Combine multiple lines output into single variable
		SELECT @SingleLineOutput = (SELECT STUFF((
		SELECT ',' + line
		FROM  @CommandShellOutputTable
		FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, ''))
    
    
	
		-- Write the 2 result variables into a temp table for summary		 
		 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;

-- Show results
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:

SQL
-- Backup database 

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.

Image 1

Hope you find this useful.

History

  • 2015-03-05 - First published

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Kitty Enterprise LLP
Canada Canada
I have been working for some corrupted government agencies in Canada who are known for scandal and milking tax payers' money. I always feel like I am in the wrong industry and want to try something more interesting because life is short. I am so tired of technologies after being in I.T. for so many years, I am a bit sick of everyday waking up and work for money, especially dealing with stupid annoying people, company politics and policies. But every time they give me a paycheck, I shut up temporary. Then the cycle begins again.....

Comments and Discussions

 
GeneralNot bad Pin
Md. Marufuzzaman7-Mar-15 21:30
professionalMd. Marufuzzaman7-Mar-15 21:30 
GeneralMy vote of 5 Pin
Retailonline6-Mar-15 4:41
Retailonline6-Mar-15 4:41 
Great script, very useful!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.