道歉
首先,对篇幅表示歉意——这是一个奇怪的问题,所以我试图提供足够的细节以使其可重现。
太长了;博士
因此,我认为在两个 MS SQL Server 之间导出数据层应用程序*.bacpac
以迁移 Indeo ProGet 数据库实例时发现了一个问题,这会创建不一致的 bacpac。尝试导入此 bacpac 会导致错误,我希望能有第二双眼睛来关注这个问题,以确保我没有做任何愚蠢的事情......
我认为根本原因是“导出数据层应用程序”过程中的一个可能的错误,当有多个架构列使用相同的用户定义类型时,并且 UDT 绑定到验证规则 - 结果似乎是一个损坏的*.bacpac
文件如果不先进行一些手动调整,就无法导入。
我的问题是:
- 第 1 部分:我是否做错了什么,或者这是一个已知(或新)的错误?
- 第 2 部分:如果这是一个错误,您知道我可以在哪里报告它吗?
模式
下面从 Inedo ProGet 数据库重新创建了一小部分架构来演示该问题。(FWIW,我目前使用的是 SQL Server 2022 v16.0.1105.1,但我很确定它也会出现在其他版本中)。
它基本上是这样做的:
- 创建用户定义类型
YNINDICATOR
Y
将其绑定到将值限制为和 的规则N
- 创建两个表,每个表都有一个 type 列
YNINDICATOR
(请参阅[dbo].[CustomLanguage].[Active_Indicator]
和[dbo].[ClusterNodes].[Primary_Indicator]
)
CREATE TYPE [dbo].[YNINDICATOR] FROM [char](1) NULL
GO
CREATE RULE [dbo].[YNINDICATOR_Domain]
AS
@Ind COLLATE Latin1_General_BIN IN ('Y', 'N');
EXEC sp_bindrule 'YNINDICATOR_Domain', 'YNINDICATOR'
GO
CREATE TABLE [dbo].[CustomLanguages](
[CustomLanguage_Id] [int] IDENTITY(1,1) NOT NULL,
[Culture_Name] [varchar](50) NOT NULL,
[Language_Name] [nvarchar](100) NOT NULL,
[Active_Indicator] [dbo].[YNINDICATOR] NOT NULL,
[CustomLanguage_Xml] [xml] NOT NULL,
CONSTRAINT [PK__CustomLanguages] PRIMARY KEY CLUSTERED
(
[CustomLanguage_Id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[ClusterNodes](
[Server_Name] [nvarchar](64) NOT NULL,
[NodeType_Code] [char](1) NOT NULL,
[LastUpdated_Date] [datetime] NOT NULL,
[Primary_Indicator] [dbo].[YNINDICATOR] NOT NULL,
[Node_Configuration] [xml] NOT NULL,
CONSTRAINT [PK__ClusterNodes] PRIMARY KEY CLUSTERED
(
[Server_Name] ASC,
[NodeType_Code] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[ClusterNodes] WITH CHECK ADD CONSTRAINT [CK__ClusterNodes__NodeType_Code] CHECK (([NodeType_Code]='S' OR [NodeType_Code]='W'))
GO
ALTER TABLE [dbo].[ClusterNodes] CHECK CONSTRAINT [CK__ClusterNodes__NodeType_Code]
GO
错误
将上述架构导出到数据层应用程序 bacpac 文件中完成,没有任何错误,但尝试将其作为新数据库重新导入时会出现以下错误:
微软 SQL Server 管理工作室
无法导入包。
错误 SQL72014:框架 Microsoft SqlDataClient 数据提供程序:MSG 2714,级别 16,状态 3,过程 YNINDICATOR_Domain,第 1 行 数据库中已存在名为“YNINDICATOR_Domain”的对象。
错误 SQL72045:脚本执行错误。执行的脚本:
创建规则 [dbo].[YINDICATOR_Domain]
AS @Ind COLLATE Latin1_General_BIN IN ('Y', 'N')
(微软.SqlServer.Dac)
调查
我解压了 bacpac,发现当使用 UDT 定义多个YNINDICATOR
列时,model.xml
bacpac 内的文件包含类似这样的内容,其中定义了两个 SqlRule
元素[dbo].[YNINDICATOR_Domain]
- 第一个包含列引用,第二个包含 UDT参考:
bacpac 损坏 - 两个列引用和一个 UDT 引用 -> 两个 SqlRule 元素
... snip ...
<Element Type="SqlRule" Name="[dbo].[YNINDICATOR_Domain]">
<Property Name="ExpressionScript">
<Value><![CDATA[@Ind COLLATE Latin1_General_BIN IN ('Y', 'N')]]></Value>
</Property>
<Relationship Name="BoundTargets">
<Entry>
<References Name="[dbo].[CustomLanguages].[Active_Indicator]" />
</Entry>
<Entry>
<References Name="[dbo].[ClusterNodes].[Primary_Indicator]" />
</Entry>
</Relationship>
<Relationship Name="Schema">
<Entry>
<References ExternalSource="BuiltIns" Name="[dbo]" />
</Entry>
</Relationship>
</Element>
<Element Type="SqlRule" Name="[dbo].[YNINDICATOR_Domain]">
<Property Name="ExpressionScript">
<Value><![CDATA[@Ind COLLATE Latin1_General_BIN IN ('Y', 'N')]]></Value>
</Property>
<Relationship Name="BoundTargets">
<Entry>
<References Name="[dbo].[YNINDICATOR]" />
</Entry>
</Relationship>
<Relationship Name="Schema">
<Entry>
<References ExternalSource="BuiltIns" Name="[dbo]" />
</Entry>
</Relationship>
</Element>
... snip ...
这可能是错误的原因,already an object named 'YINDICATOR_Domain'
因为它尝试创建 SqlRule 两次 - 每个创建一次Element
。
如果我使用 UDT删除任一列YNINDICATOR
并重新导出数据层应用程序,则 bacpac 包含一个Element Type="SqlRule"
节点,其中包含该列和UDT 引用:
工作 bacpac - 一列引用和 UDT 引用 -> 一个 SqlRule 元素
... snip ...
<Element Type="SqlRule" Name="[dbo].[YNINDICATOR_Domain]">
<Property Name="ExpressionScript">
<Value><![CDATA[@Ind COLLATE Latin1_General_BIN IN ('Y', 'N')]]></Value>
</Property>
<Relationship Name="BoundTargets">
<Entry>
<References Name="[dbo].[CustomLanguages].[Active_Indicator]" />
</Entry>
<Entry>
<References Name="[dbo].[YNINDICATOR]" />
</Entry>
</Relationship>
<Relationship Name="Schema">
<Entry>
<References ExternalSource="BuiltIns" Name="[dbo]" />
</Entry>
</Relationship>
</Element>
... snip ...
如果我使用sp_unbindrule
删除绑定,则 bacpac 仅包含一个绑定Element
- 它不再为 UDT 绑定创建第二个绑定,因为它显然不再存在:
工作 bacpac - 两列引用,无UDT 引用 -> 一个 SqlRule 元素
<Element Type="SqlRule" Name="[dbo].[YNINDICATOR_Domain]">
<Property Name="ExpressionScript">
<Value><![CDATA[@Ind COLLATE Latin1_General_BIN IN ('Y', 'N')]]></Value>
</Property>
<Relationship Name="BoundTargets">
<Entry>
<References Name="[dbo].[CustomLanguages].[Active_Indicator]" />
</Entry>
<Entry>
<References Name="[dbo].[ClusterNodes].[Primary_Indicator]" />
</Entry>
</Relationship>
<Relationship Name="Schema">
<Entry>
<References ExternalSource="BuiltIns" Name="[dbo]" />
</Entry>
</Relationship>
</Element>
虽然我无法真正使用这两个选项中的任何一个,因为它与 ProGet 应用程序的实际数据库模式不匹配,但有趣的是要注意列和 UDT 绑定如何根据是否有一个或多个进行序列化使用 UDT 的列。
解决方法
如果我手动修改model.xml
原始 bacpac 文件中的 并合并两个 SqlRule Element
,这样只有一个包含列和规则绑定,我可以很好地导入它,并且它会创建所有架构对象而不会出现错误:
但这并不是很有用,因为我不想每次迁移数据库时都必须继续执行此操作(我不会执行多次,但足以让这是一个痛苦的解决方法)。
工作 bacpac - 两个列引用和一个 UDT 引用被黑入一个SqlRule 元素
<Element Type="SqlRule" Name="[dbo].[YNINDICATOR_Domain]">
<Property Name="ExpressionScript">
<Value><![CDATA[@Ind COLLATE Latin1_General_BIN IN ('Y', 'N')]]></Value>
</Property>
<Relationship Name="BoundTargets">
<Entry>
<References Name="[dbo].[CustomLanguages].[Active_Indicator]" />
</Entry>
<Entry>
<References Name="[dbo].[ClusterNodes].[Primary_Indicator]" />
</Entry>
<Entry>
<References Name="[dbo].[YNINDICATOR]" />
</Entry>
</Relationship>
<Relationship Name="Schema">
<Entry>
<References ExternalSource="BuiltIns" Name="[dbo]" />
</Entry>
</Relationship>
</Element>
旁注:如果我重新导出该数据库,它将恢复为 2 个 SqlRule 元素的原始形式 - 一个包含列,另一个包含规则绑定。
更新
Az CLI 也会出现此问题:
PS> az version
{
"azure-cli": "2.56.0",
"azure-cli-core": "2.56.0",
"azure-cli-telemetry": "1.1.0",
"extensions": {
"storage-preview": "1.0.0b1"
}
}
PS> az sql db export `
--subscription "My Subscription" `
--resource-group "my-resource-group" `
--server "my-sql-server" `
--name "ProGet" `
--admin-user "my-admin-user" `
--admin-password "my-admin-password" `
--storage-uri "https://mystorageaccount.blob.core.windows.net/proget-db-backups/proget.bacpac" ``
--storage-key-type "StorageAccessKey" `
--storage-key "my storage key"
下载 blob 并解压它会显示多个 SqlRule 的问题Element
。
回顾
如果您已经读到这里,那么感谢您的阅读,回顾一下,我在顶部“tl;dr”中的问题是:
- 第 1 部分:我是否做错了什么,或者这是一个已知(或新)的错误?
- 第 2 部分:如果这是一个错误,您知道我可以在哪里报告它吗?
非常感谢任何帮助。