Database versioning updated
I have been getting some feedback on my blog post about database change management, and I thought it was about time to make some updates to the database change management powershell script that I posted there. Let's go through this, step by step.
My change management procedure means that I will rebuild the database from scratch for each build. Before building the database, I need to drop the old one.
We could check if the database exists before we try to drop.
# Get server reference $s = new-object ("Microsoft.SqlServer.Management.Smo.Server") $sql_server
foreach($db in $s.databases) { # Database exists? if ($db.name -eq $databasename) { $exists = $TRUE } } } catch { Write-Error "Failed to connect to $sqlserver" }
# Return $exists }
Start by creating a new database and add a versioning table to it, where we keep track of the database version.
# Instantiate the database object and create database $db = new-object ('Microsoft.SqlServer.Management.Smo.Database') ($s, $dbname) $db.Create()
# Create table and column for handling database version $db.ExecuteNonQuery("CREATE TABLE [$databaseName].[dbo].Settings"); $db.ExecuteNonQuery("INSERT INTO [$databaseName].[dbo].Settings VALUES (0)"); }
And now we can look through the directory that contains the change scripts and execute them on the database, one by one.
$databaseVersion = Get-Database-Version $connection_string
# Get all source files that have higher database version number $files = Get-ChildItem "$databasedirectory*.sql" | Where { [int]::Parse($.name.Substring(0, 4)) -gt $databaseVersion }
# For each of those files, run query on database foreach ($file in $files) { $fileName = $file.name Write-Host "Apply update script: $fileName"
# Get-Content returns a string array of all the lines. We join that into a single string $fileContents = Get-Content "$file" $sql = [string]::Join([Environment]::NewLine, $fileContents); Execute-Sql-Query $connectionString $sql
# Get this version number $version = [int]::Parse($fileName.Substring(0, 4))
# Update the settings database with current version number Execute-Sql-Query $connectionString "UPDATE [Settings] SET [DatabaseVersion] = $version" } }
Last, there's some helper functions for the functions used above.
$sql = "SELECT TOP 1 [DatabaseVersion] FROM [Settings]" ## Connect to the data source and open it $connection = New-Object System.Data.SqlClient.SqlConnection $connectionString $connection.Open()
$command = New-Object System.Data.SqlClient.SqlCommand $sql,$connection $version = $command.ExecuteScalar();
$connection.Close() $version }
Function Validate-Connection ([string]$connectionString) {
try { ## Connect to the data source and open it $connection = New-Object System.Data.SqlClient.SqlConnection $connectionString $connection.Open() $connection.Close() $TRUE } catch { $FALSE } }
Function Execute-Sql-Query ([string]$connectionString, [string]$sql) {
## Connect to the data source and open it $connection = New-Object System.Data.SqlClient.SqlConnection $connectionString $connection.Open()
$server = New-Object Microsoft.SqlServer.Management.Smo.Server($connection) $server.ConnectionContext.ExecuteNonQuery($sql) | out-null
$connection.Close() }
Thanks to Gary Murphy for his contribution to Execute-Sql-Query, and getting it to work properly with GO-statements. You will find his blog at http://garyjmurphy.com/.
The whole script can be found in its repository on bitbucket.