feanz
10/22/2013 - 2:52 PM

Powershell Migration tool http://stackingcode.com/blog/2011/10/12/database-migrations-with-powershell

DECLARE @CurrentVersion [nvarchar](100)
SELECT @CurrentVersion = [Current] FROM [dbo].[Version]
PRINT @CurrentVersion
# Copyright 2010 - 2011 Adam Boddington
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

param(
    [string]$Server         = $(throw "Server required."),
    [string]$Database       = $(throw "Database required."),
    [switch]$Maximum,
    [switch]$Minimum,
    [switch]$Rollback,
    [string]$Target)

$ErrorActionPreference = "Stop"

"" # Write line.

# Ensure the Version table exists and has a record.
SQLCMD.EXE -S $Server -d $Database -E -i ensure-version-table.sql -b
""

# Get the current version from the database.
$CurrentVersion = SQLCMD.EXE -S $Server -d $Database -E -i  print-current-version.sql -b

# Find all migrations. Each subdirectory is a migration.
$MigrationDirectories = Get-ChildItem | Where-Object { $_.PSIsContainer }

if (!$MigrationDirectories) { "No migrations to run."; ""; exit }

# [NONE] is a special case for no migrations applied.
$Migrations = @("[NONE]") + ($MigrationDirectories | ForEach-Object -Process { $_.Name })

$CurrentVersionIndex = [array]::IndexOf($Migrations, $CurrentVersion)

if ($CurrentVersionIndex -eq -1) { throw "Current version not found. (" + $CurrentVersion + ")" }

"Current Version: " + $CurrentVersion

# Determine target version index from the flags or target.
if      ($Maximum)  { $TargetVersionIndex = $Migrations.Count - 1 }
elseif  ($Minimum)  { $TargetVersionIndex = 0 }
elseif  ($Rollback) { $TargetVersionIndex = $CurrentVersionIndex - 1 }
else                { $TargetVersionIndex = [array]::IndexOf($Migrations, $Target) }

if ($Rollback -and $TargetVersionIndex -eq -1) { throw "Nothing to rollback." }
if ($TargetVersionIndex -eq -1) { throw "Target version not found. (" + $Target + ")" }

$TargetVersion = $Migrations[$TargetVersionIndex]

" Target Version: " + $TargetVersion
""

if ($CurrentVersionIndex -eq $TargetVersionIndex) { "No migrations to run."; ""; exit }

# Initialise an empty array to collect the migration scripts.
$MigrationScripts = @()

# Collect the up migration scripts.
for ($x = $CurrentVersionIndex + 1; $x -le $TargetVersionIndex; $x++) {
    $MigrationScripts += $MigrationDirectories[$x - 1].Name | Join-Path -ChildPath up.sql }

# Collect the down migration scripts.
for ($x = $CurrentVersionIndex; $x -gt $TargetVersionIndex; $x--) {
    $MigrationScripts += $MigrationDirectories[$x - 1].Name | Join-Path -ChildPath down.sql }

"Migration Scripts"
"================="
$MigrationScripts
""

# Build the migration script.
$Go = "`r`nGO`r`n"
"BEGIN TRANSACTION" + $Go | Out-File -FilePath migration.sql
$MigrationScripts | ForEach-Object -Process { (Get-Content -Path $_) + $Go | Out-File -FilePath migration.sql -Append }
"UPDATE [dbo].[Version] SET [Current] = '" + $TargetVersion + "'" + $Go | Out-File -FilePath migration.sql -Append
"COMMIT TRANSACTION" + $Go | Out-File -FilePath migration.sql -Append

# Execute the migration script.
"Executing Migration Scripts"
"==========================="
SQLCMD.EXE -S $Server -d $Database -E -i migration.sql -b
""
PRINT 'Checking the existence of the Version table.'
IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Version]') AND type IN (N'U'))
BEGIN
    PRINT 'The Version table does not exist.'
    PRINT 'Creating the Version table...'
    CREATE TABLE [dbo].[Version] ([Current] [nvarchar](100) NOT NULL)
END

PRINT 'Checking the existence of a row in the Version table.'
IF NOT EXISTS (SELECT 1 FROM [dbo].[Version])
BEGIN
    PRINT 'A row does not exist in the Version table.'
    PRINT 'Creating a row in the Version table...'
    INSERT [dbo].[Version] VALUES ('[NONE]')
END