April 18, 2011 at 7:57 am
I guess at the end of the day, I want to understand
1) why the transfer method fails on 2 out of 53 databases, given that the syscontraints view exists in all of them. (I've checked the status in sysobjects, it's identical across the board)
2) As a system object, why is it being scripted at all?
3) How can explicitly exclude it in my Powershell script?
April 20, 2011 at 1:36 pm
I got it working, finally!!!
I thought I would share what I've learned the hard way about transferring data between a SQL 2K sp4 source server and a SQL 2K8 R2 destination server. The $MovingBox variable from the example posted on the MSDN site was invaluable.
1) $xfr.Options.AllowSystemObjects = $false
In my case, the transfer class still tried to copy sysconstraints, which caused errors on the destination.
2) $dstdb.DatabaseOptions.QuotedIdentifiersEnabled = $true
This was not enough to allow the creation of a unique constraint on a computed column.
Neither was setting the value as a default connection option on the destination server.
I had to create the constraint in a script post-transfer. This is apparently a known bug.
(Also, had to drop the constraint in a script pre-transfer, and re-create at the source post-transfer.
#================= BEGIN CODE ==================
$null = [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo")
$null = [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum")
$null = [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$null = [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended")
$null = [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo.Database")
$SrcSrv = "<SourceServer>"
$DstSrv = "<DestinationServer>"
$Ssrv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server $SrcSrv
$Dsrv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server $DstSrv
$dbExceptions = "[<AnyDBYouDontWantTransferred]",...
#$ssrvdbs = $Ssrv.Databases | Where-Object {$_.name -eq "<SingleDBToTranfer>"}
$ssrvdbs = $Ssrv.Databases # All DBs.
$sdb = $null
# "Option Explicit"
set-psdebug -strict
foreach($sdb in $ssrvdbs) {
if (($dbExceptions -contains $sdb) -eq $false) # Skip DBs in the exception list.
{
$tTime = Get-Date
$dbname = "$sdb"
$dbname = $dbname.Replace("[", "")
$dbname = $dbname.Replace("]", "")
Write-host -BackgroundColor Red $tTime ": Starting DB: "$dbname
#If destination db does not exist, create it
$dstdb = $dsrv.Databases["$dbname"]
if (!$dstdb)
{
$dbCopy = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Database -argumentlist $dsrv, "$dbname"
$dbCopy.Create()
$dstdb = $dsrv.Databases["$dbname"]
}
# Set recovery mode to simple for the transfer
$dstdb.DatabaseOptions.RecoveryModel = [Microsoft.SqlServer.Management.Smo.RecoveryModel]::Simple
# Set Quoted Identifiers
$dstdb.DatabaseOptions.QuotedIdentifiersEnabled = $true
$dstdb.DatabaseOptions.AnsiNullsEnabled = $true
$dstdb.DatabaseOptions.AnsiWarningsEnabled = $true
$dstdb.DatabaseOptions.ArithmeticAbortEnabled = $true
$dstdb.DatabaseOptions.ConcatenateNullYieldsNull = $true
# Apply new settings
$dstdb.Alter()
# Here, do anything that needs to be done Pre-transfer on Source Server and/or Destination Server
# For example, I had an unique constraint on a computed column. For whatever reason, this transfer class
# connects with QuotedIdentifier OFF, which prevents the Unique constraint from being created (also, crashes
# the transfer. So I drop the constraint at the source, and re-create it post transfer using Invoke-SqlCmd
# on a SQL script.
#Define a Transfer object and set the required options and properties.
$xfr = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Transfer -argumentlist $sdb
#Define a container for the objects to transfer.
$moving_box = New-Object -TypeName "System.Collections.ArrayList"
# Set Destination options
$xfr.DestinationDatabase = $dbname
$xfr.DestinationServer = $Dsrv.Name
$xfr.DestinationLoginSecure = $true
#Transfer object properties
$xfr.PreserveDbo = $true
$xfr.DropDestinationObjectsFirst = $true
$xfr.CopyAllObjects = $false
# $xfr.CopyAllDatabaseTriggers = $true
# $xfr.CopyAllDefaults = $true
# $xfr.CopyAllStoredProcedures = $true
# $xfr.CopyAllTables = $true
# $xfr.CopyAllUserDefinedFunctions = $true
# $xfr.CopyAllUserDefinedTableTypes = $true
# $xfr.CopyAllViews = $false
# $xfr.CopyData = $true
# $xfr.CopyAllRoles = $true
# $xfr.CopyAllSchemas = $false
# $xfr.CopyAllLogins = $false
# $xfr.CopyAllUsers = $false
# $xfr.CopySchema = $true
# Transfer object options
$xfr.Options.DriAll = $true
$xfr.Options.DriForeignKeys = $true
$xfr.Options.DriUniqueKeys = $true
$xfr.Options.DriChecks = $true
$xfr.Options.DriUniqueKeys = $true
$xfr.Options.Triggers = $true
$xfr.Options.Permissions = $true
$xfr.Options.ClusteredIndexes = $true
$xfr.Options.NonClusteredIndexes = $true
$xfr.Options.AllowSystemObjects = $false
# $xfr.Options.IncludeDatabaseRoleMemberships = $false
$xfr.Options.ContinueScriptingOnError = $true
$xfr.Options.WithDependencies = $false
# This section was necessary for a couple of reasons: simply setting the transfer object properties (the lines above
# which are commented out, and begin with $xfr.CopyAllxxx) resulted in objects being scripted in the wrong order,
# i.e., functions failing on create because the underlying tables had not yet been created.
#Objects to copy
$sdb.Roles | where {$_.IsFixedRole -eq $false -and $_.name -ne "public"} | foreach {$null = $moving_box.Add($_)}
# $sdb.Tables | where {$_.IsSystemObject -eq $false -and ($_.name -eq "Keywords" -or $_.name -eq "ContLang_Type")} | foreach {$null = $moving_box.Add($_)}
$sdb.Tables | where {$_.IsSystemObject -eq $false} | foreach {$null = $moving_box.Add($_)}
$sdb.UserDefinedFunctions | where {$_.IsSystemObject -eq $false} | foreach {$null = $moving_box.Add($_)}
$sdb.StoredProcedures | where {$_.IsSystemObject -eq $false} | foreach {$null = $moving_box.Add($_)}
$sdb.Views | where {$_.IsSystemObject -eq $false} | foreach {$null = $moving_box.Add($_)}
$xfr.ObjectList = $moving_box
$xfr.TransferData()
# Scripting Data Transfer
# $xfr.Options.ToFileOnly = $true
# $xfr.Options.FileName = "C:\XFer.sql"
# $xfr.ScriptTransfer()
# Do the transfer
# $xfr.TransferData()
# Set dst db compatibility level to 8.
#$Command = "EXEC sp_dbcmptlevel '$dbname', 100"
#Invoke-sqlcmd -ServerInstance $DstSrv -Database $dbname -Query $Command
# Any post-transfer stuff goes here, for instance, my dropped Unique constraint from above,
# re-created on Source and Destination DBs.
# Set recovery model back to Full, other DB options
$dstdb.DatabaseOptions.RecoveryModel = [Microsoft.SqlServer.Management.Smo.RecoveryModel]::Full
$dstdb.Alter()
$tTime = Get-Date
Write-host -BackgroundColor Green $tTime ": Completed DB: "$dbname
}
}
#================= END CODE ==================
Viewing 2 posts - 16 through 17 (of 17 total)
You must be logged in to reply to this topic. Login to reply
This website stores cookies on your computer.
These cookies are used to improve your website experience and provide more personalized services to you, both on this website and through other media.
To find out more about the cookies we use, see our Privacy Policy