SSDT 项目 Post 使用 Merge 和 'WHEN NOT MATCHED By SOURCE THEN DELETE' 为具有外键约束的表设定种子时的部署问题
SSDT project Post Deployment issues when seeding tables with foreign key constraints using Merge coupled with 'WHEN NOT MATCHED By SOURCE THEN DELETE'
我有一个 SSDT 项目,我使用 MERGE 语句在我的 Script.PostDeployment.sql 文件中播种 table。问题是当我查找相互依赖的 tables 并且我从那些 tables MERGE 脚本中删除记录时,我得到了外键约束。
假设我有两个查找 tables:
CREATE TABLE [dbo].[Parent] (
ParentId INT NOT NULL IDENTITY(1,1)
)
CREATE TABLE [dbo].[Child] (
ChildId INT NOT NULL IDENTITY(1,1),
ParentId INT NOT NULL,
CONSTRAINT [FK_Parent_Child] FOREIGN KEY ([ParentId]) REFERENCES [dbo].[Parent] ([ParentId])
)
我的Script.PostDeployment.sql脚本:
:r .\Parent.Seed.sql
:r .\Child.Seed.sql
我的Parent.Seed.sql脚本
SET IDENTITY_INSERT [dbo].[Parent] ON
MERGE INTO [dbo].[Parent] as parent
USING (VALUES (1,2,3)) seed ([ParentId])
ON parent.ParentId = seed.ParentId
WHEN MATCHED THEN
UPDATE SET [ParentId] = seed.[ParentId]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([ParentId])
VALUES ([ParentId])
WHEN NOT MATCHED BY SOURCE THEN DELETE;
SET IDENTITY_INSERT [dbo].[Parent] OFF
GO
我的Child.Seed.sql脚本:
SET IDENTITY_INSERT [dbo].[Child] ON
MERGE INTO [dbo].[Child] as child
USING (VALUES
(1,1)
,(2,2)
,(3,3)
) seed ([ChildId], [ParentId])
ON child.ChildId = seed.ChildId
WHEN MATCHED THEN
UPDATE SET [ParentId] = seed.[ParentId]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([ChildId],[ParentId])
VALUES ([ChildId],[ParentId])
WHEN NOT MATCHED BY SOURCE THEN DELETE;
SET IDENTITY_INSERT [dbo].[Child] OFF
GO
这在最初第一次为数据库做种时工作正常但是当您修改种子脚本时因为现在假设我想从 Parent.Seed.sql
脚本中删除 3
记录然后它抛出外键约束错误,因为它首先尝试从 Parent
table 中删除 ParentId
,这违反了 [FK_Parent_Child]
约束。
我如何管理这些查找 table,因为它们总是随着我们的应用程序的发展而发展?
选项很少:
从临时 table 种子子 table 而不是合并中的硬编码值。
您将能够在几步内完成所有修改并避免 FK 违规,如插入父项、插入子项、删除子项、删除父项。
在脚本之前禁用 FK 约束,如果在脚本之后re-enable。
我不确定这对你的情况是否可行,你可以尝试 soft-delete(在你的 table 中包含已删除的列)。
我有一个 SSDT 项目,我使用 MERGE 语句在我的 Script.PostDeployment.sql 文件中播种 table。问题是当我查找相互依赖的 tables 并且我从那些 tables MERGE 脚本中删除记录时,我得到了外键约束。
假设我有两个查找 tables:
CREATE TABLE [dbo].[Parent] (
ParentId INT NOT NULL IDENTITY(1,1)
)
CREATE TABLE [dbo].[Child] (
ChildId INT NOT NULL IDENTITY(1,1),
ParentId INT NOT NULL,
CONSTRAINT [FK_Parent_Child] FOREIGN KEY ([ParentId]) REFERENCES [dbo].[Parent] ([ParentId])
)
我的Script.PostDeployment.sql脚本:
:r .\Parent.Seed.sql
:r .\Child.Seed.sql
我的Parent.Seed.sql脚本
SET IDENTITY_INSERT [dbo].[Parent] ON
MERGE INTO [dbo].[Parent] as parent
USING (VALUES (1,2,3)) seed ([ParentId])
ON parent.ParentId = seed.ParentId
WHEN MATCHED THEN
UPDATE SET [ParentId] = seed.[ParentId]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([ParentId])
VALUES ([ParentId])
WHEN NOT MATCHED BY SOURCE THEN DELETE;
SET IDENTITY_INSERT [dbo].[Parent] OFF
GO
我的Child.Seed.sql脚本:
SET IDENTITY_INSERT [dbo].[Child] ON
MERGE INTO [dbo].[Child] as child
USING (VALUES
(1,1)
,(2,2)
,(3,3)
) seed ([ChildId], [ParentId])
ON child.ChildId = seed.ChildId
WHEN MATCHED THEN
UPDATE SET [ParentId] = seed.[ParentId]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([ChildId],[ParentId])
VALUES ([ChildId],[ParentId])
WHEN NOT MATCHED BY SOURCE THEN DELETE;
SET IDENTITY_INSERT [dbo].[Child] OFF
GO
这在最初第一次为数据库做种时工作正常但是当您修改种子脚本时因为现在假设我想从 Parent.Seed.sql
脚本中删除 3
记录然后它抛出外键约束错误,因为它首先尝试从 Parent
table 中删除 ParentId
,这违反了 [FK_Parent_Child]
约束。
我如何管理这些查找 table,因为它们总是随着我们的应用程序的发展而发展?
选项很少:
从临时 table 种子子 table 而不是合并中的硬编码值。
您将能够在几步内完成所有修改并避免 FK 违规,如插入父项、插入子项、删除子项、删除父项。在脚本之前禁用 FK 约束,如果在脚本之后re-enable。
我不确定这对你的情况是否可行,你可以尝试 soft-delete(在你的 table 中包含已删除的列)。