Sql 在插入行之前验证值是否存在

Sql 在插入行之前验证值是否存在,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个查询,其中我发送了一个TableType,其中包含列EmpKey和TaskId,如: @AssignNotificationTableType [dbo].[udf_TaskNotification] READONLY INSERT INTO [TaskNotification] ([TaskId], [EmpKey]) SELECT [ANT].[TaskId], [E].[EmpKey] FROM @AssignNotifica

我有一个查询,其中我发送了一个TableType,其中包含列
EmpKey
TaskId
,如:

  @AssignNotificationTableType [dbo].[udf_TaskNotification] READONLY

INSERT INTO [TaskNotification] ([TaskId], [EmpKey])
    SELECT
        [ANT].[TaskId], [E].[EmpKey]
    FROM 
        @AssignNotificationTableType AS [ANT]
    INNER JOIN 
        [Employee] AS [E] ON [ANT].[EmpGuid] = [E].[EmpGuid]
所以我的桌子看起来像这样:

+--------------------------------------+--------------------------------------+--------+
|          TaskNotificationId          |                TaskId                | EmpKey |
+--------------------------------------+--------------------------------------+--------+

| EEE3D3F8-F190-E811-841F-C81F66DACA6A | D0440DEB-404C-4006-870F-E95BFFA840E0 |     44 |
| EFE3D3F8-F190-E811-841F-C81F66DACA6A | D0440DEB-404C-4006-870F-E95BFFA840E0 |     49 |
+--------------------------------------+--------------------------------------+--------+
正如您可以看到的,两个项目具有相同的
TaskId
但不同的
Empkey
,因此假设如果我再次发送相同的
TaskId
D0440DEB-404C-4006-870F-E95BFFA840E0
,我只想在该任务ID中不存在Empkey时插入行

因此,如果我发送如下内容:

+--+--------------------------------------+--------+
|  |                TaskId                | EmpKey |
+--+--------------------------------------+--------+
|  | D0440DEB-404C-4006-870F-E95BFFA840E0 |     44 |
|  | D0440DEB-404C-4006-870F-E95BFFA840E0 |     49 |
|  | D0440DEB-404C-4006-870F-E95BFFA840E0 |     54 |
+--+--------------------------------------+--------+
它将只插入最后一行,因为
EmpKey
54不存在于该
TaskId

我尝试在
WHERE
子句中使用
NOT in
作为:

INSERT INTO [TaskNotification] ([TaskId], [EmpKey])
    SELECT
        [ANT].[TaskId], [E].[EmpKey]
    FROM 
        @AssignNotificationTableType AS [ANT]
    INNER JOIN 
        [Employee] AS [E] ON [ANT].[EmpGuid] = [E].[EmpGuid]
    WHERE 
        [E].[EmpKey] NOT IN (SELECT EmpKey
                             FROM [TaskNotification]
                             WHERE TaskId = (SELECT TaskId 
                                             FROM @AssignNotificationTableType))

但当我运行它时,它不会插入任何内容。我做错了什么?将目标表作为左联接添加到select语句中:

INSERT INTO [TaskNotification]
(
     [TaskId]
    , [EmpKey]
)
 SELECT
       [ANT].[TaskId]
     , [E].[EmpKey]
       FROM @AssignNotificationTableType AS [ANT]
           INNER JOIN [Employee] AS [E] ON [ANT].[EmpGuid] = [E].[EmpGuid]
           LEFT JOIN [TaskNotification] AS [TN] ON [TN].[TaskId] = [ANT].[TaskId]
               AND [TN].[EmpKey] = [E].[EmpKey]
       WHERE [TN].[PK] IS NULL -- PK stands for the primary key column 
       -- (or first column in of a multiple columns pk)

但是,请注意,在多线程环境中,这种查询可能会失败-有关详细信息,请阅读Dan Guzman的博客文章并将其链接到。

将目标表作为左连接添加到select语句:

INSERT INTO [TaskNotification]
(
     [TaskId]
    , [EmpKey]
)
 SELECT
       [ANT].[TaskId]
     , [E].[EmpKey]
       FROM @AssignNotificationTableType AS [ANT]
           INNER JOIN [Employee] AS [E] ON [ANT].[EmpGuid] = [E].[EmpGuid]
           LEFT JOIN [TaskNotification] AS [TN] ON [TN].[TaskId] = [ANT].[TaskId]
               AND [TN].[EmpKey] = [E].[EmpKey]
       WHERE [TN].[PK] IS NULL -- PK stands for the primary key column 
       -- (or first column in of a multiple columns pk)

然而,请注意,在多线程环境中,这种查询可能会失败-有关更多信息,请阅读Dan Guzman的博客文章并将其链接到。

为什么要使用“WHERE TaskId=(从@AssignNotificationTableType中选择TaskId)”?如果我不使用它,它会获取employee表中的所有员工,或者我错了?如果我删除它,它只是相同的结果,它不会插入任何内容@alvaroparray如果您在表变量中发送多个行,则上一个子查询将失败。您应该使用NOT EXISTS而不是NOT IN为什么要使用“WHERE TaskId=(从@AssignNotificationTableType中选择TaskId)”?如果我不使用它,它会获取employee表中的所有员工,或者我错了?如果我删除它,它只是相同的结果,它不会插入任何内容@alvaroparray如果您在表变量中发送多个行,则上一个子查询将失败。您应该在最后一个where子句中使用NOT EXISTS而不是NOT IN where PK字段<代码>其中[TN].[PK]为空?我尝试了这个方法,但我仍然有相同的问题不应该“[TN].[EmpKey]=[ANT].[EmpKey]”是“[TN].[EmpKey]=[E].[EmpKey]”?我真的很困惑。。。我不知道什么是
[TN].[PK]
@UnhandledExcepSeanYes,“[TN].[EmpKey]=[ANT].[EmpKey]”是“[TN].[EmpKey]=[E].[EmpKey]”。和[TN].[PK]-用
TN
表的主键列替换
PK
(任何不可为NULL的列都可以,主键也会被索引,这样它会有更好的执行计划。最后一个where子句中的PK字段是什么?
其中[TN].[PK]为NULL
?我尝试了这个方法,但我仍然有相同的问题不应该“[TN].[EmpKey]”=[ANT].[EmpKey]“be”[TN].[EmpKey]=[E].[EmpKey]?我真的很困惑……我不知道什么是
[TN].[PK]
@UnhandledExcepSeanYes,[TN].[EmpKey]=[ANT].[EmpKey]“be”[TN].[EmpKey]=[E].[E].[EmpKey].[TN].[PK]-用
TN
表的主键列替换
PK
(任何不可为null的列都可以,主键也会被索引,因此它会有更好的执行计划。