I stripped out a piece of company-specific logic, but…
List the databases you want to move in a file named “control.txt.” (To migrate the entire server, paste the output of “select name from sys.databases where name not in (‘master’, ‘msdb’, ‘model’, ‘tempdb’).”)
Replace the example values in the below script with real information:
@ECHO ON set controlfile=control.txt set newipmdf=\\newserver\g$ set newipldf=\\newserver\e$ set oldserver=oldserver\Prod1 set oldmdfpath=d:\prod1 set newmdfpath=g:\data set copymdfpath=m:\data set newserver=newserver set oldlogpath=e:\prod1 set newlogpath=e:\log set copylogpath=l:\log set movedmdfpath=%oldmdfpath%\moved set movedldfpath=%oldlogpath%\moved mkdir %movedmdfpath% mkdir %movedldfpath% net use m: %newipmdf% net use l: %newipldf% SETLOCAL DISABLEDELAYEDEXPANSION FOR /F %%L IN (%controlfile%%) DO ( SET "line=%%L" SETLOCAL ENABLEDELAYEDEXPANSION ECHO !line! sqlcmd -E -S!oldserver! -Q"EXEC master.dbo.sp_detach_db @dbname = N'!line!'" copy "!oldmdfpath!\!line!.mdf" !copymdfpath! copy "!oldlogpath!\!line!_log.ldf" !copylogpath! sqlcmd -E -S!newserver! -Q"CREATE DATABASE [!line!] ON ( FILENAME = N'!newmdfpath!\!line!.mdf' ),( FILENAME = N'!newlogpath!\!line!_log.ldf' ) FOR ATTACH" move "!oldmdfpath!\!line!.mdf" !movedmdfpath! move "!oldlogpath!\!line!_log.ldf" !movedldfpath! ENDLOCAL ) ENDLOCAL net use m: /z net use l: /z
(The redacted data was a sharding-related item–updating a metadata table with the new location. You can, of course, add your own logic after the attach, if needed.)
As always, I’ve included a downloadable version here.