Backup a database from Azure SQL Managed Instance and restore to on premise SQL Server I have three databases that I am migrating to Azure SQL Managed Instance. One is a Utility database, just a small collection of generic functions and procedures. One is the OLTP database for a web application. The third is a read-only archive of the OLTP database containing historic data for analysis and reporting as well as audit tables. I need to be able to restore these databases to on premise development and test servers. So far, I have been unsuccessful. 

My first attempt was to use backup to Azure Blob Storage. But no matter what version of SQL Server I use locally, I always get an error that the Copy Only backup is from a newer version and restore is not supported.

Next, I tried Export Data tier application from SSMS v.18.1. Unfortunately, it never gets past the export. I get dozens of errors that read External references are not supported when creating a package from this platform. One of the greatest strengths of Managed Instance over Azure SQL DB is the ability to do cross-database queries. I have a number of views and procedures that link tables in the two databases. Additionally, some procedures in the OLTP database call the functions in the Utility database. Since MI is not Azure SQL database, you would think this wouldn't be a problem! 

Searching Google, I found this question on Stack Overflow. So I tried the Visual Studio approach proposed as an answer. Although it appears to work, meaning it creates a multi-gigabyte file on my local machine, attempting to import that file using SSMS gives me an error that reads No data is present in this file. So then I tried the second possible solution using sqlpackage.exe. But that solution doesn't work for me either as it only references exporting the schema. And if I try to export the whole database with /Action:Export I get the same error message as SSMS gives. 

I also examined this Database Administrators question. No help - that is what I originally attempted. If anyone has any other thoughts I would greatly appreciate hearing them!
I've been able to export data from an Azure Managed Instance (MI) to a SQL Server 2012 system successfully without the need of Visual Studio. 


Using SQL Server Management Studio (SSMS) right click on the database in you want to copy choose Tasks &gt; Export Data-tier Application. Choose where to save the .bacpac file that is created.


A .bacpac file is a zip file containing XML that defines your tables and relationships along with BCP files that store the data of each table.

If you have 7zip extract the bacpac file to see the contents. If you don't, you can rename the file extensions from .bacpac to .zip and extract it using File Explorer (right click > Extract All...)
Open the model.xml file in your favourite text editor and look for the attribute called CompatibilityMode. This will have been set to the compatibility level of the MI (currently 150). Change it to the compatibility level you are importing to. I was importing to SQL 2012 so changed it to 110.
Remove any other incompatible features by commenting out the relevant line in model.xml.


For example, SQL 2012 can't do In-Memory tables so I had to comment out this section from the model.xml file:



    &lt;!--&lt;Element Type="SqlFilegroup" Name="[XTP]"&gt;
            &lt;Property Name="ContainsMemoryOptimizedData" Value="True" /&gt;
    &lt;/Element&gt;--&gt;



Setting the Value to false may also work.


Putting it back together. Microsoft have added some simple validation to tell if the bacpac file is corrupt or has been tampered with. If you have made any changes to model.xml file you will need to calculate a new checksum value for it. The value is stored in the Origin.xml file in the bacpac.

You can generate a new checksum value by using PowerShell:


Get-FileHash -Path C:\Path\To\Extracted\bacpac\model.xml | Format-Table -Property Hash


You should get an output like this:

Hash
----
ED8754D205946850F3CED0B033342BF3D88A43E146E57D861191AACC1AC1659A



Open the Origin.xml file from the extracted bacpac files and look for a line like this at the end and replace the existing hash value with the new one:

&lt;Checksums&gt;
  &lt;Checksum Uri="/model.xml"&gt;ED8754D205946850F3CED0B033342BF3D88A43E146E57D861191AACC1AC1659A&lt;/Checksum&gt;
&lt;/Checksums&gt;


Make sure you don't add any spaces or extraneous characters.

Now zip the files back up making sure the top level of the archive is the files and not the folder you extracted everything too. If you open the new file you should see the xml files and not a single folder name.

You should now be able to import the bacpac into your non-Azure SQL database.

Some notes  about bacpac backups:


They may not be transactionally consistent. For an export to be transactionally consistent, you must ensure either that no write activity is occurring during the export, or that you are exporting from a transactionally consistent copy of your Azure SQL database.
If you are exporting to blob storage, the maximum size of a BACPAC file is 200 GB. To archive a larger BACPAC file, export to local storage.