Friday, November 19, 2010

Generate DB script using PowerShell

This is an example script that can be used to dump a SQL Server database schema into a creation script. The advantages of this method over using SQL Server Management Studio include:
  • Scriptable. Can be included in a build or commit script.
  • Repeatable. SQL Server Management Studio generated scripts vary from run to run, so it can be difficult to make comparisons with previous versions of the schema in source control.
  • Repeatable. Using the SQL Server Management Studio GUI to create scripts relies on everyone ticking the same boxes to generate consistent and correct DB scripts.
  • Configurable. This script ignores objects (e.g. tables and triggers) with names starting with 'test'.
<#
.SYNOPSIS
.NOTES
Author: 
#>

$root = resolve-path ((split-path -path $MyInvocation.MyCommand.Definition -Parent) + '\..\..');
$serverURL = 'SQL2005'
$databaseName = "DBToDump";
$scriptFile = "$root\Scripts\Create.sql"

#================== GetObjectsFromDB ===================
function GetObjectsFromDB(
[parameter(mandatory=$true)]$Database, 
[parameter(mandatory=$true)][string]$ObjectType)
{
    $objects = [Microsoft.SqlServer.Management.Smo.SqlSmoObject[]]($database.$ObjectType | Where-object {$_.IsSystemObject -ne $true -and $_.IsFixedRole -ne $true -and $_.Name -notmatch '^test' } );
    if($objects)
    {
        ,$objects
    }
    else
    {
        ,@()
    }
}
#=======================================================

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
$server = new-object Microsoft.SqlServer.Management.Smo.Server ($serverURL);
$server.SetDefaultInitFields([Microsoft.SqlServer.Management.SMO.StoredProcedure], "IsSystemObject")
$db = $server.Databases[$databaseName];

if(Test-Path $scriptFile)
{
    del $scriptFile
}

$scripter = new-object Microsoft.SqlServer.Management.Smo.Scripter ($server);
$options = $scripter.Options
$options.ScriptDrops = $false
$options.IncludeIfNotExists = $false
$options.ScriptData = $false
$options.NoCommandTerminator = $false
$options.FileName = $scriptFile
$options.SchemaQualify = $true
$options.ToFileOnly = $true
$options.AppendToFile = $true
$options.DriAllConstraints = $true
$options.Indexes = $true
$options.ClusteredIndexes = $true
$options.Statistics = $true
$options.IncludeDatabaseRoleMemberships = $true
$options.TargetServerVersion = [Microsoft.SqlServer.Management.Smo.SqlServerVersion]::Version90
$options.NoFileGroup = $true
$options.DriAll = $true

echo "Scripting database..."
$scripter.EnumScript($db)

#don't script collation for DB objects since it has been done for the database as a whole
$options.NoCollation = $true

#switch to newly created DB
"
USE [$databaseName]
GO
" | out-file -append $scriptFile -ErrorAction stop

$objects = GetObjectsFromDB $db "Schemas"
$objects += GetObjectsFromDB $db "Roles"
$objects += GetObjectsFromDB $db "Tables"
$objects += GetObjectsFromDB $db "UserDefinedFunctions"
$objects += GetObjectsFromDB $db "StoredProcedures"
$objects += GetObjectsFromDB $db "Views"

$scripter.EnumScript($objects)

echo "Done."

#set permissions (not sure how to script the ones I want without including test permissions)
"
GRANT EXECUTE ON SCHEMA::[app] TO [application] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[cfg] TO [application] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[cfg] TO [support] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[dbo] TO [support] AS [dbo]
GO
GRANT UPDATE ON SCHEMA::[cfg] TO [support] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[sup] TO [support] AS [dbo]
GO
GRANT VIEW DEFINITION ON SCHEMA::[sup] TO [support] AS [dbo]
GO
GRANT VIEW DEFINITION ON SCHEMA::[cfg] TO [support] AS [dbo]
GO
GRANT VIEW DEFINITION ON SCHEMA::[dbo] TO [support] AS [dbo]
GO
GRANT EXECUTE ON SCHEMA::[sup] TO [support] AS [dbo]
GO" | out-file -append $scriptFile -ErrorAction stop

0 comments:

Post a Comment