错误将Azure bacpac文件导入到本地数据库错误EXTERNAL附近的语法不正确

时间:2017-02-03 16:34:29

标签: sql azure import bacpac

将db from azure bacpac文件导入本地sql server 2016时,我发现了以下错误。

Error SQL72014: .Net SqlClient Data Provider: Msg 102, Level 15, State 1, Line 1 Incorrect syntax near 'EXTERNAL'.
Error SQL72045: Script execution error.  The executed script: CREATE EXTERNAL DATA SOURCE [BoxDataSrc]
    WITH (
    TYPE = RDBMS,
    LOCATION = N'MYAZUREServer.database.windows.net',
    DATABASE_NAME = N'MyAzureDb',
    CREDENTIAL = [SQL_Credential]
    );

(Microsoft.SqlServer.Dac)

6 个答案:

答案 0 :(得分:4)

我今天遇到了同样的问题。因为" WITH(TYPE = RDBMS)"仅适用于Azure SQL DB,我们在尝试将bacpac导入SQL Server 2017内部部署时收到错误。由于这篇文章,我确实找到了解决方案:

https://blogs.msdn.microsoft.com/azuresqldbsupport/2017/08/16/editing-a-bacpac-file/

此处重写相关步骤:

  1. 制作bacpac文件的副本(出于出错的安全性)。
  2. 将文件扩展名更改为zip,然后将其解压缩到一个文件夹中。令人惊讶的是,bacpac实际上只是一个zip文件,而不是专有的,很难进入。
  3. 找到model.xml文件并对其进行编辑,以删除如下所示的部分:

    <Element Type="SqlExternalDataSource" Name="[BoxDataSrc]">
        <Property Name="DataSourceType" Value="1" />
        <Property Name="Location" Value="MYAZUREServer.database.windows.net" />
        <Property Name="DatabaseName" Value="MyAzureDb" />
        <Relationship Name="Credential">
            <Entry>
                <References Name="[SQL_Credential]" />
            </Entry>
        </Relationship>
    </Element>
    
  4. 如果您有多个此类外部数据源,则可能需要为每个外部数据源重复步骤3。我只有一个。

  5. 保存并关闭model.xml。
  6. 现在你需要重新生成model.xml的校验和,这样bacpac就不会认为它被篡改了(因为你刚刚篡改了它)。创建名为computeHash.ps1的PowerShell文件并将此代码放入其中。

    $modelXmlPath = Read-Host "model.xml file path"
    $hasher = [System.Security.Cryptography.HashAlgorithm]::Create("System.Security.Cryptography.SHA256CryptoServiceProvider")
    $fileStream = new-object System.IO.FileStream ` -ArgumentList @($modelXmlPath, [System.IO.FileMode]::Open)
    $hash = $hasher.ComputeHash($fileStream)
    $hashString = ""
    Foreach ($b in $hash) { $hashString += $b.ToString("X2") }
    $fileStream.Close()
    $hashString
    
  7. 运行PowerShell脚本并将文件路径提供给解压缩和编辑的model.xml文件。它将返回校验和值。

  8. 复制校验和值,然后打开Origin.xml并将现有的校验和替换为如下所示的行的底部:

    <Checksum Uri="/model.xml">9EA0F06B282D4F42955C78A98822A31AA0ED0225CB131B8759379055A482D01F</Checksum>
    
  9. 保存并关闭Origin.xml,然后选择所有文件并将其放入新的zip文件中,并将扩展名重命名为bacpac。

  10. 现在,您可以使用此新bacpac导入数据库而不会收到错误。它对我有用,它也适合你。

答案 1 :(得分:1)

根据@SQLDoug的回答,如果您的Azure SQL数据库具有外部表(即来自其他数据库的链接表),则可能会发生这种情况。您可以在此处在SSMS中进行检查:

External Tables node in SSMS

已接受答案的附录

如果删除这些外部表的数据源,则还需要删除model.xml文件中也使用这些数据源的SqlExternalTable元素,它们的外观将如下所示:

   <Element Type="SqlExternalTable" Name="[dbo].[DeliveryMethodsRestored]">
        <Property Name="ExternalSchemaName" Value="dbo" />
        <Property Name="ExternalObjectName" Value="DeliveryMethods" />
        <Property Name="IsAnsiNullsOn" Value="True" />
        <Property Name="IsQuotedIdentifierOn" Value="False" />
        <Relationship Name="Columns">
            <Entry>
                <Element Type="SqlSimpleColumn" Name="[dbo].[DeliveryMethodsRestored].[DeliveryMethodId]">
                    <Property Name="IsNullable" Value="False" />
                    <Relationship Name="TypeSpecifier">
                        <Entry>
          SNIP....
    </Element>

如果在model.xml中搜索“ SqlExternalTable”,您将很容易找到它们。

解决此问题的替代方法

下载bacpac之后,除了更正bacpac之外,另一种解决方法是在创建bacpac之前先删除外部表,即:

  1. 将数据库的副本还原到单独的数据库
  2. 删除已还原副本中的外部表

External Tables node in SSMS

  1. 删除已还原副本中的外部数据源

enter image description here

  1. 从已还原的副本创建bacpac
  2. 删除副本数据库

此方法的优点是您无需从实时数据库(显然是'can cause the exported table data to be inconsistent because, unlike SQL Server's physical backup/restore, exports do not guarantee transactional consistency')中创建bacpac。

如果这是您可能要做的事情,那么您可能可以编写脚本来自动完成上述大多数步骤。

答案 2 :(得分:0)

仅在Azure SQL数据库v12或更高版本上支持弹性数据库查询,而不在本地服务器上。 https://msdn.microsoft.com/en-us/library/dn935022.aspx

答案 3 :(得分:0)

@SQLDoug的回答的另一点是-在压缩bacpac文件时,重要的是内容不在文件夹内。相反,它们必须位于zip文件的顶层。

请在this msdn article上找到详细说明。

答案 4 :(得分:0)

相同的错误代码,但有不同的错误。

无法导入包。 警告SQL72012:对象[PreProd_Data]存在于目标中,但是即使选中了“为目标数据库中的对象而不是源中的对象生成放置语句”复选框,也不会将其删除。

警告SQL72012:对象[PreProd_Log]存在于目标中,但即使您选中了“为目标数据库中的对象而不是源中的对象生成放置语句”复选框,也不会将其删除。

错误SQL72014:.Net SqlClient数据提供程序:消息102,级别15,状态1,第5行,“ OPTIMIZE_FOR_AD_HOC_WORKLOADS”附近的语法不正确。

错误SQL72045:脚本执行错误。执行的脚本: 如果存在(选择1            从[master]。[dbo]。[sysdatabases]            其中[名称] = N'$(DatabaseName)')     开始         ALTER DATABASE SCOPED CONFIGURATION SET OPTIMIZE_FOR_AD_HOC_WORKLOADS = ON;     结束

解决方案

此博客将帮助编辑model.xml,以删除OPTIMIZE_FOR_AD_HOC_WORKLOADS的Relationship命令,这在SQL Server 2017实例中是不需要的。

https://blogs.msdn.microsoft.com/azuresqldbsupport/2017/08/16/editing-a-bacpac-file/

制作bacpac文件的副本(以确保发生错误时的安全)。 将文件扩展名更改为zip,然后将其解压缩到文件夹中。出人意料的是,bacpac实际上只是一个zip文件,而不是专有且难以使用的文件。 找到model.xml文件并对其进行编辑,以删除如下所示的部分:

相关步骤在此处重写:

  1. 制作bacpac文件的副本(以防万一出错)。

  2. 将文件扩展名更改为zip,然后将其解压缩到文件夹中。 令人惊讶的是,bacpac实际上只是一个zip文件,不是什么 专有且难以进入。

  3. 找到model.xml文件并对其进行编辑以删除看起来像是的部分 像这样:

    <Relationship Name="GenericDatabaseScopedConfigurationOptions">
        <Entry>
            <References Name="[OPTIMIZE_FOR_AD_HOC_WORKLOADS]" />
        </Entry>
    </Relationship>
    
  4. 从model.xml中删除以下代码段

    <Element Type="SqlGenericDatabaseScopedConfigurationOptions" Name="[OPTIMIZE_FOR_AD_HOC_WORKLOADS]">
        <Property Name="GenericValueType" Value="2" />
        <Property Name="GenericValue" Value="ON" />
    </Element>
    
  5. 保存并关闭model.xml。

  6. 现在,您需要重新生成model.xml的校验和,以便bacpac不会认为它已被篡改(因为您刚刚对其进行了篡改)。创建一个名为computeHash.ps1的PowerShell文件,并将此代码放入其中。

  7. 运行PowerShell脚本,并为其提供已解压缩和编辑的model.xml文件的文件路径。它将返回一个校验和值。

  8. 复制校验和值,然后打开Origin.xml并替换现有的校验和。

  9. 保存并关闭Origin.xml,然后选择所有文件并将其放入新的zip文件中,并将扩展名重命名为bacpac。

现在bacpack文件将可以导入了,并且对我有用。

谢谢。

答案 5 :(得分:0)

我在导入 bacpac 时遇到了相同的错误代码 (SQL72045),即使我们已经删除了 Azure 中用于同步数据的外部数据源。结果发现,有一个程序“TransferDo”参考了另一个数据库的 SCOPED CREDENTIAL。删除程序后,导入运行良好。