将 Azure bacpac 文件导入本地数据库时出错,在 EXTERNAL 附近出现错误语法

Posted

技术标签:

【中文标题】将 Azure bacpac 文件导入本地数据库时出错,在 EXTERNAL 附近出现错误语法【英文标题】:Error Importing Azure bacpac file to local db error incorrect syntax near EXTERNAL 【发布时间】:2017-06-21 02:19:59 【问题描述】:

将 db fro 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)

【问题讨论】:

你有没有想过如何解决这个问题? 【参考方案1】:

在导入 bacpac 时,我得到了相同的错误代码 (SQL72045),即使我们已经删除了 Azure 中用于同步数据的外部数据源。事实证明,参考另一个数据库的 SCOPED CREDENTIAL 留下了一个过程“TransferDo”。在我们删除该过程后,导入工作正常。

【讨论】:

我们可以删除哪个步骤? @cuongle 在制作 bacpac 之前删除程序【参考方案2】:

相同的错误代码不同的错误。

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

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

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

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

解决方案

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

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

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

这里重写了相关步骤:

    制作 bacpac 文件的副本(以防出错)。

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

    找到 model.xml 文件并编辑它以删除看起来像的部分 像这样:

    <Relationship Name="GenericDatabaseScopedConfigurationOptions">
        <Entry>
            <References Name="[OPTIMIZE_FOR_AD_HOC_WORKLOADS]" />
        </Entry>
    </Relationship>
    

    从 model.xml 中删除以下块

    <Element Type="SqlGenericDatabaseScopedConfigurationOptions" Name="[OPTIMIZE_FOR_AD_HOC_WORKLOADS]">
        <Property Name="GenericValueType" Value="2" />
        <Property Name="GenericValue" Value="ON" />
    </Element>
    

    保存并关闭 model.xml。

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

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

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

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

现在 bacpack 文件已准备好导入,它对我有用。

谢谢。

【讨论】:

【参考方案3】:

根据@SQLDoug 的回答,如果您的 Azure SQL 数据库具有外部表(即来自其他数据库的链接表),则可能会发生这种情况。您可以在此处的 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 删除副本数据库

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

如果这是您可能经常做的事情,您可能会编写脚本来自动化上述大部分步骤。

【讨论】:

另一种方法很简单,也很直接。谢谢。【参考方案4】:

我今天遇到了同样的问题。由于“WITH(TYPE = RDBMS)”仅适用于 Azure SQL DB,因此在尝试将 bacpac 导入本地 SQL Server 2017 时出现错误。感谢这篇文章,我确实找到了解决方案:

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

这里重写了相关步骤:

    制作 bacpac 文件的副本(以防出错)。 将文件扩展名更改为 zip,然后将其解压缩到一个文件夹中。令人惊讶的是,bacpac 实际上只是一个 zip 文件,而不是专有且难以进入的东西。

    找到 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>
    

    如果您有多个这种类型的外部数据源,您可能需要对每个数据源重复第 3 步。我只有一个。

    保存并关闭 model.xml。

    现在您需要重新生成 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
    

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

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

    <Checksum Uri="/model.xml">9EA0F06B282D4F42955C78A98822A31AA0ED0225CB131B8759379055A482D01F</Checksum>
    

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

现在您可以使用这个新的 bacpac 导入数据库而不会出现错误。它对我有用,也对你有用。

【讨论】:

太棒了!!。它工作正常。以后使用该数据库会不会有什么问题? 仅供参考,我必须使用 $hasher = New-Object System.Security.Cryptography.SHA256CryptoServiceProvider 来获取我的 $hasher。 在 powershell 脚本中,您可能需要在末尾添加类似 Read-Host -Prompt "Press Enter to exit" 以保持输出可见。【参考方案5】:

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

【讨论】:

以上是关于将 Azure bacpac 文件导入本地数据库时出错,在 EXTERNAL 附近出现错误语法的主要内容,如果未能解决你的问题,请参考以下文章

Azure SQL 数据库 Bacpac 本地还原

在 Azure 中创建加密的 bacpac 文件

尝试将 BACPAC 从 blob 存储导入到 ssms 时收到 CREATE USER 错误

即使选项在防火墙设置中设置为 yes,Azure SQL Server 防火墙也不允许操作连接

使用 SqlPackage 导入 bacpac 数据库,检查存在并指定位置

使用 CLI 工具 (sqlpackage.exe / PS dbatools) 时通过 BACPAC / DACPAC 导入数据库在用户上失败