Skip to content

Copy-DbaDatabase to bulk migrate databases to custom directories on destination #10587

Description

@tholiveira1

Summarize Functionality

Copy-DbaDatabase has no parameter to control where a database's data/log/FILESTREAM files are restored on the destination. The only directory-related parameter is SharedPath, which is the staging location for backup files as well documented. Every migrated database ends up restored to whatever the destination instance's single default data/log path is (or the source's original path, depending on internal logic), with no way to place each database into its own subfolder.

By contrast, Restore-DbaDatabase (which Copy-DbaDatabase presumably wraps internally for its backup/restore mode) already exposes exactly this: DestinationDataDirectory, DestinationLogDirectory, DestinationFileStreamDirectory.

Is there a command that is similiar or close to what you are looking for?

Yes

Technical Details

my requirement was to have each database data/log/fs folder on destination in it's own directory by database, it's a bulk migration.
to reproduce the error use below:
$dbs = Get-DbaDatabase -SqlInstance $source -ExcludeSystem

foreach ($db in $dbs) {
$migrateDbSplat = @{
Source = $source
Destination = $destination
Database = $db.Name
BackupRestore = $true
SharedPath = '\share\backups'
Force = $true
DestinationDataDirectory = "D:\Data$($db.Name)"
DestinationLogDirectory = "E:\Log$($db.Name)"
DestinationFileStreamDirectory = "F:\Filestream$($db.Name)"
}
Copy-DbaDatabase @migrateDbSplat -verbose
}

error per db:
Copy-DbaDatabase : A parameter cannot be found that matches parameter name 'DestinationDataDirectory'.
Copy-DbaDatabase : A parameter cannot be found that matches parameter name 'DestinationFileStreamDirectory'.

working replacement

foreach ($db in $dbs) {
$backupSplat = @{
SqlInstance = $source
Database = $db.Name
Path = '\share\backups'
Verbose = $true
}

$restoreSplat = @{
    SqlInstance              = $destination
    DestinationDataDirectory = "D:\Data\$($db.Name)"
    DestinationLogDirectory  = "E:\Log\$($db.Name)"
    WithReplace              = $true
    Verbose                  = $true
}

$hasFileStream = [bool](Get-DbaDbFile -SqlInstance $source -Database $db.Name |
    Where-Object TypeDescription -eq 'FILESTREAM')

if ($hasFileStream) {
    $restoreSplat.DestinationFileStreamDirectory = "F:\Filestream\$($db.Name)"
}

Backup-DbaDatabase @backupSplat | Restore-DbaDatabase @restoreSplat

}

--this worked as expected, migrated a bulk of databases, created individual folders on dest and restored each db to it's own data/log/filestream folder

####added note
Without DestinationFileStreamDirectory, Copy-DbaDatabase -BackupRestore doesn't error on FILESTREAM databases — it silently restores the FILESTREAM container to whatever the implicit default location is (in testing, this landed inside the regular data directory rather than any FILESTREAM-specific path), reporting Status: Successful the whole time in my case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featuretriage requiredNew issue that has not been reviewed by maintainers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions