有没有办法在单个可执行脚本中对三个表进行幂等插入?
Is there any way to make a idempotent insert of three tables in a single executable script?
我目前正在使用 .net 应用程序工作,当您结帐到不同的 git 分支时,该应用程序使用脚本刷新所有数据库。情况是当此脚本 'refreshes' 并清除该分支中的所有旧测试数据时,还会执行名为 'migrations' 的文件夹中的所有迁移文件。所以我正在尝试创建一个迁移,以使用幂等性在某些表中插入一些特定的值。此迁移文件必须与 'migrations' 文件夹中的其他文件一样(幂等)以便每次执行脚本时都执行,这样它就不会重复数据,保持结构并被执行多次并离开数据库处于相同状态。
插页是:
USE [$defaultDB]
GO
INSERT INTO [dbo].[Catalog]
([name]
,[description]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[modifiedIn]
,[isActive]
,[catalogTypeID])
VALUES
('PolicyClasificationID',
'Id de clasificación de póliza',
2,
2022-01-20 13:43:09.687,
'127.0.0.1',
2,
2022-01-20 13:43:09.687,
'127.0.0.1',
1,
1,
)
GO
INSERT INTO [dbo].[CatalogItem]
([catalogID]
,[catalogFlavorID]
,[parentCatalogItemID]
,[name]
,[displayLabel]
,[description]
,[catalogValue]
,[sequence]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[isActive]
,[parentCatalogID]
,[parentCatalogValueID])
VALUES
(271, 1, NULL, 'Fidem', 'FIDEM', NULL, 1, 1, 2, '2022-01-20 12:41:12.203', '127.0.0.1', 2, '2022-01-20 12:41:12.203', 1, NULL, NULL)
(271, 1, NULL, 'Bac', 'BAC', NULL, 2, 2, 2, '2022-01-21 12:41:12.203', '127.0.0.1', 2, '2022-01-21 12:41:12.203', 1, NULL, NULL)
GO
INSERT INTO [dbo].[CompanyComponentFlavor]
([companyID]
,[componentID]
,[subComponentID]
,[flavorID])
VALUES
(3,
7,
271,
1)
END
如有任何帮助,我们将不胜感激。
没问题。让我们以您的 CatalogItem
table 为例,因为您尝试插入多行,因此从概念上讲它是最具挑战性的。但是,如您所见, 并不具有挑战性。
MERGE [dbo].[CatalogItem] AS tgt
USING (
SELECT *
FROM (VALUES
(271, 1, NULL, 'Fidem', 'FIDEM', NULL, 1, 1, 2, '2022-01-20 12:41:12.203', '127.0.0.1', 2, '2022-01-20 12:41:12.203', 1, NULL, NULL),
(271, 1, NULL, 'Bac', 'BAC', NULL, 2, 2, 2, '2022-01-21 12:41:12.203', '127.0.0.1', 2, '2022-01-21 12:41:12.203', 1, NULL, NULL)
) as x(
[catalogID]
,[catalogFlavorID]
,[parentCatalogItemID]
,[name]
,[displayLabel]
,[description]
,[catalogValue]
,[sequence]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[isActive]
,[parentCatalogID]
,[parentCatalogValueID]
)
) AS src
ON src.[catalogID] = tgt.[catalogID]
WHEN NOT MATCHED BY TARGET THEN
INSERT (
[catalogID]
,[catalogFlavorID]
,[parentCatalogItemID]
,[name]
,[displayLabel]
,[description]
,[catalogValue]
,[sequence]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[isActive]
,[parentCatalogID]
,[parentCatalogValueID]
)
VALUES (
src.[catalogID]
,src.[catalogFlavorID]
,src.[parentCatalogItemID]
,src.[name]
,src.[displayLabel]
,src.[description]
,src.[catalogValue]
,src.[sequence]
,src.[createdBy]
,src.[createdOn]
,src.[createdIn]
,src.[modifiedBy]
,src.[modifiedOn]
,src.[isActive]
,src.[parentCatalogID]
,src.[parentCatalogValueID]
);
这里基本上发生了两件事。第一个是我正在使用 MERGE
语句。它允许“如果不存在则插入”类型的操作(除其他外)。它因一些奇怪的行为而声名狼藉。但是对于您描述的用例(即铺设一个核开发环境),它感觉很合适。此 MERGE 语句的所有含义是“如果目标 table 中缺少给定行(由目录 ID 标识),则将其插入”。
您可能不习惯看到的第二件事是使用行值构造函数作为数据源。这只是我几年前学会的一个技巧,当临时 table 没有意义时,我倾向于使用它。
我在这里展示的最后一件事是,您可能希望也可能不希望在所有三个 table 中“全有或全无”插入缺失数据。如果是这样,通过将“BEGIN TRAN/COMMIT”放在 begin/end(分别)处,将您想要作为一个单元执行的所有内容包装在事务中。不过,对于这种情况,这对我来说有点过分了。
我目前正在使用 .net 应用程序工作,当您结帐到不同的 git 分支时,该应用程序使用脚本刷新所有数据库。情况是当此脚本 'refreshes' 并清除该分支中的所有旧测试数据时,还会执行名为 'migrations' 的文件夹中的所有迁移文件。所以我正在尝试创建一个迁移,以使用幂等性在某些表中插入一些特定的值。此迁移文件必须与 'migrations' 文件夹中的其他文件一样(幂等)以便每次执行脚本时都执行,这样它就不会重复数据,保持结构并被执行多次并离开数据库处于相同状态。
插页是:
USE [$defaultDB]
GO
INSERT INTO [dbo].[Catalog]
([name]
,[description]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[modifiedIn]
,[isActive]
,[catalogTypeID])
VALUES
('PolicyClasificationID',
'Id de clasificación de póliza',
2,
2022-01-20 13:43:09.687,
'127.0.0.1',
2,
2022-01-20 13:43:09.687,
'127.0.0.1',
1,
1,
)
GO
INSERT INTO [dbo].[CatalogItem]
([catalogID]
,[catalogFlavorID]
,[parentCatalogItemID]
,[name]
,[displayLabel]
,[description]
,[catalogValue]
,[sequence]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[isActive]
,[parentCatalogID]
,[parentCatalogValueID])
VALUES
(271, 1, NULL, 'Fidem', 'FIDEM', NULL, 1, 1, 2, '2022-01-20 12:41:12.203', '127.0.0.1', 2, '2022-01-20 12:41:12.203', 1, NULL, NULL)
(271, 1, NULL, 'Bac', 'BAC', NULL, 2, 2, 2, '2022-01-21 12:41:12.203', '127.0.0.1', 2, '2022-01-21 12:41:12.203', 1, NULL, NULL)
GO
INSERT INTO [dbo].[CompanyComponentFlavor]
([companyID]
,[componentID]
,[subComponentID]
,[flavorID])
VALUES
(3,
7,
271,
1)
END
如有任何帮助,我们将不胜感激。
没问题。让我们以您的 CatalogItem
table 为例,因为您尝试插入多行,因此从概念上讲它是最具挑战性的。但是,如您所见, 并不具有挑战性。
MERGE [dbo].[CatalogItem] AS tgt
USING (
SELECT *
FROM (VALUES
(271, 1, NULL, 'Fidem', 'FIDEM', NULL, 1, 1, 2, '2022-01-20 12:41:12.203', '127.0.0.1', 2, '2022-01-20 12:41:12.203', 1, NULL, NULL),
(271, 1, NULL, 'Bac', 'BAC', NULL, 2, 2, 2, '2022-01-21 12:41:12.203', '127.0.0.1', 2, '2022-01-21 12:41:12.203', 1, NULL, NULL)
) as x(
[catalogID]
,[catalogFlavorID]
,[parentCatalogItemID]
,[name]
,[displayLabel]
,[description]
,[catalogValue]
,[sequence]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[isActive]
,[parentCatalogID]
,[parentCatalogValueID]
)
) AS src
ON src.[catalogID] = tgt.[catalogID]
WHEN NOT MATCHED BY TARGET THEN
INSERT (
[catalogID]
,[catalogFlavorID]
,[parentCatalogItemID]
,[name]
,[displayLabel]
,[description]
,[catalogValue]
,[sequence]
,[createdBy]
,[createdOn]
,[createdIn]
,[modifiedBy]
,[modifiedOn]
,[isActive]
,[parentCatalogID]
,[parentCatalogValueID]
)
VALUES (
src.[catalogID]
,src.[catalogFlavorID]
,src.[parentCatalogItemID]
,src.[name]
,src.[displayLabel]
,src.[description]
,src.[catalogValue]
,src.[sequence]
,src.[createdBy]
,src.[createdOn]
,src.[createdIn]
,src.[modifiedBy]
,src.[modifiedOn]
,src.[isActive]
,src.[parentCatalogID]
,src.[parentCatalogValueID]
);
这里基本上发生了两件事。第一个是我正在使用 MERGE
语句。它允许“如果不存在则插入”类型的操作(除其他外)。它因一些奇怪的行为而声名狼藉。但是对于您描述的用例(即铺设一个核开发环境),它感觉很合适。此 MERGE 语句的所有含义是“如果目标 table 中缺少给定行(由目录 ID 标识),则将其插入”。
您可能不习惯看到的第二件事是使用行值构造函数作为数据源。这只是我几年前学会的一个技巧,当临时 table 没有意义时,我倾向于使用它。
我在这里展示的最后一件事是,您可能希望也可能不希望在所有三个 table 中“全有或全无”插入缺失数据。如果是这样,通过将“BEGIN TRAN/COMMIT”放在 begin/end(分别)处,将您想要作为一个单元执行的所有内容包装在事务中。不过,对于这种情况,这对我来说有点过分了。