创建一个 SQL 脚本,将多个项目插入 table 但首先检查每个项目是否存在

Creating a SQL Script that inserts several items into a table but checking if each exist first

在 SQL Server Management Studio 中,我转到生成脚本并创建一个如下所示的 INSERT 脚本:

SET IDENTITY_INSERT [dbo].[Product] ON 
GO
INSERT [dbo].[Product] ([Id], [Name]) VALUES (1, N'Product 1')
GO
INSERT [dbo].[Product] ([Id], [Name]) VALUES (2, N'Product 2')
GO
INSERT [dbo].[Product] ([Id], [Name]) VALUES (3, N'Product 3')
GO
SET IDENTITY_INSERT [dbo].[Product] OFF
GO

假设我有多个客户端数据库,我希望能够在所有这些数据库上安全地 运行 此脚本,无论这些产品是否已经存在。我真的必须用 if exists 包装每一个插入行还是有更好的方法?

最终计划是在 SQL SERVER 数据库项目中将其用作 Post-部署脚本,用于包含系统设置等项目的表。

SET IDENTITY_INSERT [dbo].[Product] ON 
GO
INSERT [dbo].[Product] ([Id], [Name]) 
select id,name from products t where not exists(select 1 from products t2 where t2.id=t1.id and t2.name=t1.name
GO
SET IDENTITY_INSERT [dbo].[Product] OFF

为什么不一步完成所有插入?

INSERT [dbo].[Product] ([Id], [Name])
    SELECT id, name
    FROM (VALUES (1, N'Product 1'),
                 (2, N'Product 2')
                 (3, N'Product 3')
         ) v(Id, Name)
    WHERE NOT EXISTS (SELECT 1 FROM Product P2 WHERE p2.id = v.id);

我最近遵循的一种模式,可能也适合您的情况:

SELECT name
INTO #My_Table
FROM dbo.My_Table
WHERE 1=0

INSERT INTO #My_Table
VALUES
    ('One'),
    ('Two')
    ... etc.

INSERT INTO dbo.My_Table (id, name)
SELECT id, name
FROM #My_Table
WHERE name NOT IN (SELECT name FROM My_Table)

DROP TABLE #My_Table

这假定 id 只是一个 IDENTITY 列,并且 name 是带有 UNIQUE 约束的真实标识符。如果你的结构不同,那么你可以相应地调整。

如果行的唯一性由多个列确定,那么您可以使用另一种方法来检查是否存在(LEFT OUTER JOIN 并检查 NULL 或子查询等)

我发现这让我可以将 table 中的所有数据以方便、易于阅读的格式保存在 VALUES.

中易于维护