web-dev-qa-db-ja.com

SMO v11(SQL Server 2012)がキー定義、インデックス、および制約をスクリプト化しない

.ps1中央管理サーバーで実行されるPowerShellスクリプト。スクリプトは、環境内のすべてのデータベースに送信され、すべてのオブジェクトにスクリプトが送信されます。テーブルスクリプトの場合、出力ファイルには常に、制約、主キー、およびインデックスとともにテーブル定義が含まれています。

最近、CMSをPowershell 3.0とSQL Server 2012にアップグレードし、出力スクリプトにはテーブル定義のみが含まれるようになりました。インデックス、制約、およびキー定義は、スクリプトの一部ではなくなりました。このSQL Server 2012リリースでのSMOの変更点と、問題の解決方法を誰かが知っていますか?.

私のコードは以下です。

# LoopInstances

$InstanceListFile = "C:\temp\serverlist.txt"
$CurrentDay = Get-Date -Format dd
$InstanceList = Get-Content $InstanceListFile

foreach ($InstanceName in $InstanceList)
{
    if (($InstanceName -ne 'Server1') -and ($InstanceName -ne 'Server2'))
    {
    # Configuration
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMOExtended')  | out-null
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Replication") | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.RMO") | Out-Null

    $MyScripter = New-Object "Microsoft.SqlServer.Management.SMO.Scripter"

    $InstanceObject = New-Object "Microsoft.SqlServer.Management.SMO.Server" "$InstanceName"

    $RepInstanceObject = New-Object "Microsoft.SqlServer.Replication.ReplicationServer" "$InstanceName"

    # The SetDefaultInitFields method tells the SMO API to add the IsSystemObject property to the default list for this session

    $InstanceObject.SetDefaultInitFields("Microsoft.SqlServer.Management.SMO.ExtendedStoredProcedure", "IsSystemObject")
    $InstanceObject.SetDefaultInitFields("Microsoft.SqlServer.Management.SMO.StoredProcedure", "IsSystemObject")
    $InstanceObject.SetDefaultInitFields("Microsoft.SqlServer.Management.SMO.Table", "IsSystemObject")
    $InstanceObject.SetDefaultInitFields("Microsoft.SqlServer.Management.SMO.View", "IsSystemObject")
    $InstanceObject.SetDefaultInitFields("Microsoft.SqlServer.Management.SMO.UserDefinedFunction", "IsSystemObject")
    $MyScripter.Server = $InstanceObject
    $ScripterOptions = $MyScripter.Options

    # SetScriptOptions

    $ScripterOptions.ToFileOnly = $True
    $ScripterOptions.AppendToFile = $True
    $ScripterOptions.ContinueScriptingOnError = $True
    $ScripterOptions.LoginSid = $True
    $ScripterOptions.AgentAlertJob = $True
    $ScripterOptions.AgentNotify = $True
    $ScripterOptions.Bindings = $True
    $ScripterOptions.DriAll = $True
    $ScripterOptions.Indexes = $True
    $ScripterOptions.Permissions = $True
    $ScripterOptions.SchemaQualify = $True
    $ScripterOptions.Triggers = $True
    $ScripterOptions.IncludeIfNotExists = $True
    $ScripterOptions.ExtendedProperties = $True

    # SetSchemaPath


    $SchemaPath = "C:\Temp\" + $CurrentDay + "\" + $InstanceName
    if ((Test-Path $SchemaPath) -ne $True) {mkdir $SchemaPath | Out-Null} 

    # DisplayInstance

    Write-Host "------------------------------------------------------------"
    Write-Host $InstanceName - (Get-Date)
    Write-Host "------------------------------------------------------------"

    # CheckVersion

    if ($InstanceObject.Information.VersionString.substring(0,2) -eq 10)
    {

        $InstanceObjectList = "Audits","BackupDevices","Credentials","CryptographicProviders","Databases","EndPoints","LinkedServers","Logins","ServerAuditSpecifications","Triggers","UserDefinedMessages"
        $JobServerObjectList = "AlertCategories","Alerts","JobCategories","Jobs","OperatorCategories","Operators","ProxyAccounts","SharedSchedules","TargetServerGroups","TargetServers"
        $DatabaseObjectList = "Assemblies","AsymmetricKeys","Certificates","DatabaseAuditSpecifications","Defaults","ExtendedProperties","FullTextCatalogs","FullTextStopLists","PartitionFunctions","PartitionSchemes","PlanGuides","Roles","Rules","Schemas","Synonyms","Triggers","UserDefinedAggregates","UserDefinedDataTypes","UserDefinedTableTypes","UserDefinedTypes","Users","XmlSchemaCollections"
    }

    if ($InstanceObject.Information.VersionString.substring(0,1) -eq 9)
    {
        $InstanceObjectList = "BackupDevices","Credentials","Databases","EndPoints","LinkedServers","Logins","Triggers","UserDefinedMessages"
        $JobServerObjectList = "AlertCategories","Alerts","JobCategories","Jobs","OperatorCategories","Operators","ProxyAccounts","SharedSchedules","TargetServerGroups","TargetServers"
        $DatabaseObjectList = "Assemblies","AsymmetricKeys","Certificates","Defaults","ExtendedProperties","FullTextCatalogs","PartitionFunctions","PartitionSchemes","Roles","Rules","Schemas","Synonyms","Triggers","UserDefinedAggregates","UserDefinedDataTypes","UserDefinedTypes","Users","XmlSchemaCollections"
    }

    if ($InstanceObject.Information.VersionString.substring(0,1) -eq 8)
    {
        $InstanceObjectList = "BackupDevices","Databases","LinkedServers","Logins","UserDefinedMessages"
        $JobServerObjectList = "AlertCategories","Alerts","JobCategories","Jobs","OperatorCategories","Operators","TargetServerGroups","TargetServers"
        $DatabaseObjectList = "Defaults","ExtendedProperties","FullTextCatalogs","Roles","Rules","UserDefinedDataTypes","Users"
    }

    # ScriptInstance

    Write-Host Instance
    foreach($Object in $InstanceObjectList)
    {
        Write-Host "    " $Object


        $ScripterOptions.FileName=$SchemaPath + "\Instance_" + $Object + ".sql"


        if ((Test-Path $ScripterOptions.FileName) -eq $True)
        {
            del $ScripterOptions.FileName
        }


        $InstanceObjectCombined = $InstanceObject.$Object
        $MyScripter.Script([Microsoft.SqlServer.Management.Smo.SqlSmoObject[]]$InstanceObjectCombined)


        if ($? -eq $False)
        {
            Write-Host "FAILED - SCRIPT ABORTED"
        }
    }

        # ScriptJobServer

    if ($InstanceObject.Information.Edition -ne 'Express Edition')
    {
        Write-Host JobServer
        foreach($Object in $JobServerObjectList)
        {
            Write-Host "    " $Object
            $ScripterOptions.FileName=$SchemaPath + "\JobServer_" + $Object + ".sql"
            if ((Test-Path $ScripterOptions.FileName) -eq $True)
            {
                del $ScripterOptions.FileName
            }
            $InstanceObjectJobServer = $InstanceObject.JobServer.$Object
            $MyScripter.Script([Microsoft.SqlServer.Management.Smo.SqlSmoObject[]]$InstanceObjectJobServer)
            if ($? -eq $False)
            {
                Write-Host "FAILED - SCRIPT ABORTED"
#               exit 1
            }
        }
    }


        # ScriptDatabases

    $DatabaseFilter = $InstanceObject.Databases | where {$_.Name -ne "distribution"} | where {$_.Name -ne "master"} | where {$_.Name -ne "msdb"} | where {$_.Name -ne "tempdb"}
    foreach($Database in $DatabaseFilter)
    {
        Write-Host $Database
        foreach($Object in $DatabaseObjectList)
        {
            Write-Host "    " $Object
            $ScripterOptions.FileName=$SchemaPath + "\Database_" + $Database.name + "_" + $Object + ".sql"
            if ((Test-Path $ScripterOptions.FileName) -eq $True)
            {
                del $ScripterOptions.FileName
            }
            $ScripterOptions.Permissions = $True
            $InstanceObjectDatabases = $InstanceObject.Databases[$Database.name].$Object
            $MyScripter.Script([Microsoft.SqlServer.Management.Smo.SqlSmoObject[]]$InstanceObjectDatabases)
            if ($? -eq $False)
            {
                Write-Host "FAILED - SCRIPT ABORTED"
#               exit 1
            }
        }

        foreach($Object in "ExtendedStoredProcedures","StoredProcedures","Tables","Views","UserDefinedFunctions")
        {
            Write-Host "    " $Object
            $ScripterOptions.FileName=$SchemaPath + "\Database_" + $Database.name + "_" + $Object + ".sql"
            if ((Test-Path $ScripterOptions.FileName) -eq $True)
            {
                del $ScripterOptions.FileName
            }
            $ObjectFilter = $InstanceObject.Databases[$Database.name].$Object | where {$_.IsSystemObject -eq $False}
            if ($ObjectFilter)
            {
                $ScripterOptions.Permissions = $True
                $MyScripter.Script([Microsoft.SqlServer.Management.Smo.SqlSmoObject[]]$ObjectFilter)
                if ($? -eq $False)
                {
                    Write-Host "FAILED - SCRIPT ABORTED"
#                   exit 1
                }
            }
        }
    }

    # ScriptReplication - Added after all SMO scripting to avoid bug detected in losing the database context

    $RepScriptOptions = [Microsoft.SqlServer.Replication.scriptoptions]::Creation `
    -bor  [Microsoft.SqlServer.Replication.scriptoptions]::IncludeArticles `
    -bor  [Microsoft.SqlServer.Replication.scriptoptions]::IncludePublisherSideSubscriptions `
    -bor  [Microsoft.SqlServer.Replication.scriptoptions]::IncludeSubscriberSideSubscriptions

    Write-Host Replication
    foreach($ReplicatedDatabase in $RepInstanceObject.ReplicationDatabases) 
    {
        $ScriptFileName=$SchemaPath + "\Replication_" + $ReplicatedDatabase.Name + ".sql"
        if ((Test-Path $ScriptFileName) -eq $True)
        {
            del $ScriptFileName
        }
            foreach($Publication in $ReplicatedDatabase.TransPublications) 
            {
            Write-Host "    " $Publication.Name
                $Publication.Script($RepScriptOptions) >> $ScriptFileName
            if ($? -eq $False)
            {
                Write-Host "FAILED - SCRIPT ABORTED"
#               exit 1
            }
            }
            foreach($Publication in $ReplicatedDatabase.MergePublications) 
            {
            Write-Host "    " $Publication.Name
                $Publication.Script($RepScriptOptions) >> $ScriptFileName
            if ($? -eq $False)
            {
                Write-Host "FAILED - SCRIPT ABORTED"
#               exit 1
            }
            }
    }
}
4
Tamarick Hill

あなたが説明している問題を再現できません。以下は、2012および2008 R2から2008 R2サーバーへのテストに使用した簡略化されたスクリプトです。必要に応じて、add-typeセクションをコメント/コメント解除します。 1つの考えは、同じマシンに2008と2012の両方のアセンブリがある場合、廃止されたLoadWithPartialNameを使用すると問題が発生する可能性があるということです。

#SQL 2008 R2
#add-type -AssemblyName "Microsoft.SqlServer.ConnectionInfo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
#add-type -AssemblyName "Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
#add-type -AssemblyName "Microsoft.SqlServer.SMOExtended, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"

#SQL 2012
add-type -AssemblyName "Microsoft.SqlServer.ConnectionInfo, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
add-type -AssemblyName "Microsoft.SqlServer.Smo, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
add-type -AssemblyName "Microsoft.SqlServer.SMOExtended, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"

$InstanceName = "myservername"

$query = @"
CREATE TABLE dbo.authors(
    au_id int NOT NULL,
    au_lname varchar(40) NOT NULL,
    au_fname varchar(20) NOT NULL

 CONSTRAINT UPKCL_auidind PRIMARY KEY CLUSTERED 
(
    au_id ASC
)
) 
"@

$InstanceObject = New-Object "Microsoft.SqlServer.Management.SMO.Server" "$InstanceName"

$db = $InstanceObject.Databases['tempdb']
$db.ExecuteNonQuery($query)

$MyScripter = New-Object "Microsoft.SqlServer.Management.SMO.Scripter"

$MyScripter.Server = $InstanceObject

$MyScripter.Options.DriAll = $true
#$MyScripter.Options.DriPrimaryKey = $false
#$MyScripter.Options.DriClustered = $false

$MyScripter.Script($InstanceObject.Databases['tempdb'].Tables['authors'])
4
Chad Miller