Bulk Database Migration from On-Premise SQL Server to SQL Azure - Step 1: Bulk .bacpac Export
I recently had a task to perform a bulk migration of hundreds of databases to Windows Azure SQL Database (formerly known as SQL Azure) from an instance of SQL Server 2012. If you need to migrate a very small number of databases, the easiest way is likely through the SSMS export Data-Tier Application wizard. You can manually create a .bacpac file for each of the databases and move them to your blob storage. However, for hundreds of databases, this is not a nice solution. There are several ways to automate this task, but I decided to use TSQL scripting to build up the correct SQLPackage.exe command line call, then use xp_cmdshell to execute. Similarly, the script below can be modified to generate the appropriate command line syntax and be executed outside of SQL Server if needed since most SQL Server environments have xp_cmdshell disabled.
There are several different techniques for migrating an on-premise SQL Server database to SQL Database. My current technical preference is to "export" the database using Data-Tier Application functionality to create a self-contained .bacpac file (NOTE: .bacpac, not .dacpac) that can then be uploaded to blob storage and imported directly into your SQL Database environment. One benefit of using .bacpac export is that the process includes a validation step to verify that all objects in your on-premise database will be supported in SQL Database. Other techniques (scripting, Import/Export wizard, extracting .dacpacs, etc) do not perform this verification during the extraction phase and will result in a failed database creation in the SQL Database environment if you have unsupported objects (ex: a table without a clustered index). These other techniques give different benefits, such as the flexibility to manually modify scripts, etc., but for ease of use, I'm currently sticking with .bacpac export.
Task: Bulk Migration from On-Premise SQL Server to SQL Database - Step 1: Performing Bulk .bacpac Export through TSQL Scripting & SQLPackage.exe
Code Snippet
- /*
- Purpose: This script performs bacpac export for all databases in a given server. If the database contains objects fully supported in
- SQL Database / SQL Azure, then the bacpac export will succeed. If not, the errors/reasons for failure will be displayed in the result set.
- After running the script, save the output to text to help determine what objects need to be modified in order for each DB to be ready to migrate.
- Author: Sam Lester (MSFT)
- Create Date: 12/1/12
- Sample Call for bacpac export
- sqlpackage.exe /Action:Export /SourceServerName:. /sdn:"DB_Foo" /tf:"c:\MyBacpacs\DB_Foo.bacpac"
- */
- /* Create table to hold DB names to process */
- create table files(files varchar(max))
- create table publish(filename varchar(1000), cmd varchar(max))
- create table output (output varchar(1000) null)
- go
- declare @filepath varchar(1000), @dircmd varchar(1000), @sqlpackagepath varchar(1000)
- select @filepath = 'c:\MyBacpacs\'/* path to export .bacpacs -- Create this directory before running */
- ,@sqlpackagepath = 'C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\sqlpackage.exe' -- Update this to the correct location for your DacFramework.msi install
- -- Store the list of databases that we want to export. If you want a particular subset, add a WHERE clause to filter this list.
- insert into files
- select name from sys.databases where database_id > 4 --Skip the system DBs
- /* Build the command line string that we'll later execute in the WHILE loop. In this example, the instance name is hardcoded
- to the default instance (using . in /ssn:.). If you have a named instance, update this string to "/ssn:ServerName\InstanceName" */
- insert into publish
- select files, ' /Action:Export /sdn:' + files +' /ssn:. /tf:' + @filepath + files + '.bacpac'
- from files
- DECLARE @counter int, @limit int, @rc int
- SET @counter =(select count(*) from publish)
- SET @limit = 0
- -- Loop through and execute each command line to perform the export
- WHILE (@limit < @counter)
- BEGIN
- declare @txt varchar(1000)
- select @txt = 'cmd /c ""' + @sqlpackagepath + '"" ' +(select top 1 cmd from publish) + ' >> ' + @filepath + 'results_bacpac_export.txt'
- insert output select '----------------------------------------'
- insert output select top 1 cmd from publish
- insert output select '----------------------------------------'
- insert output exec @rc = master.dbo.xp_cmdshell@txt
- if (ISNULL(@rc,0) = 0)
- begin
- insert output select '--- SUCCESSFUL EXPORT FOR DATABASE = ' +(select top 1 filename from publish)
- end
- delete top (1) from publish
- select @limit = @limit + 1
- END
- select * from output where output is not null
- /* Cleanup
- drop table files
- drop table publish
- drop table output
- */
The result of running the script is the following:
1. For databases that can be successfully migrated to SQL Database, a .bacpac file is created in the file location supplied in the script. These can then be moved to blob storage and imported.
2. For databases that cannot be successfully migrated to SQL Database, the output of the script provides the list of unsupported objects. Save this output to text to help assess your migration strategy.
Ex:
Hope this helps,
Sam Lester (MSFT)
Standard disclaimer: As with any script/code, please run this in a test server to make sure it works for your specific version/edition/environment settings before tinkering in your production environment.
Comments
Anonymous
December 08, 2012
its very helpful tips for me ,thank you for share this article.Anonymous
December 28, 2012
Nice thanks to share ..Anonymous
March 10, 2015
Nice sharingAnonymous
August 08, 2015
This is nice and everything until you have around 25000 tables because then bacpacs can't be imported anymore due to the operation timing out, see: serverfault.com/.../importing-bacpac-file-with-25000-tables-on-sql-server-fails-with-timeout