有什么原因 WHERE NOT EXISTS 在我的声明中似乎不起作用吗?

b.o*_*.oa 0 sql-server

这是我的 DDL:

CREATE TABLE dbo.KeyName
(
KeyNameID INT NOT NULL  IDENTITY(1,1),
PartName VARCHAR(20) NOT NULL ,
RwVersion ROWVERSION NOT NULL 
CONSTRAINT PK_KeyName PRIMARY KEY CLUSTERED (KeyNameID)
);
Run Code Online (Sandbox Code Playgroud)

这是我的存储过程:

ALTER PROCEDURE [dbo].[uspKeyNameUpdate]
@KeyNameID INT,
@PartName VARCHAR(20),
@RwVersion BIGINT

AS

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

BEGIN
   DECLARE @newId INT = 0
   
      INSERT INTO dbo.KeyName(PartName) VALUES(@PartName)
      SELECT @PartName AS PartName
      WHERE NOT EXISTS (
      SELECT PartName FROM dbo.KeyName WHERE PartName = @PartName)

      SET @newId = SCOPE_IDENTITY()

      IF ISNULL(@newId,0) != 0
         INSERT INTO dbo.EmployeeName(KeyNameID,EmployeeID) VALUES(@newId,@KeyNameID)
END
Run Code Online (Sandbox Code Playgroud)

如果 KeyName 表中不存在 PartName,则 sp 起作用。但是,当我使用相同的详细信息第二次调用它时,它失败并出现以下错误:

Cannot insert duplicate key row in object 'dbo.KeyName' with unique index 'UX_KeyName'. The duplicate key value is (winston).
The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)

我用以下内容替换了 INSERT 块:

   IF NOT EXISTS(SELECT * FROM KeyName WHERE PartName = @PartName)
      INSERT INTO KeyName(PartName) VALUES(@PartName)
      SELECT @newId = SCOPE_IDENTITY()
      INSERT INTO EmployeeName(KeyNameID,EmployeeID) VALUES(@newId,@KeyNameID)
Run Code Online (Sandbox Code Playgroud)

同样的错误:

我现在在海上,请帮忙。

use*_*983 6

认为问题在于你认为下面的陈述是一个陈述:

      INSERT INTO dbo.KeyName(PartName) VALUES(@PartName)
      SELECT @PartName AS PartName
      WHERE NOT EXISTS (
      SELECT PartName FROM dbo.KeyName WHERE PartName = @PartName)
Run Code Online (Sandbox Code Playgroud)

这不是一个陈述,而是两个陈述;一份INSERT声明和一份SELECT声明。如果我们终止您的语句(无论如何您都应该这样做,因为不这样做是不推荐的),并添加一些额外的格式,也许这会变得更清楚:

      INSERT INTO dbo.KeyName(PartName)
      VALUES(@PartName);

      SELECT @PartName AS PartName
      WHERE NOT EXISTS (SELECT PartName
                        FROM dbo.KeyName
                        WHERE PartName = @PartName);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,因此参数@PartName始终INSERT添加到您的表中,无论它是否存在。

可能你实际上想要这样的东西:

ALTER PROCEDURE [dbo].[uspKeyNameUpdate] @KeyNameID int,
                                         @PartName varchar(20),
                                         @RwVersion bigint
AS
BEGIN
    SET NOCOUNT ON;

    IF NOT EXISTS (SELECT 1 FROM dbo.KeyName WHERE PartName = @PartName)
    BEGIN
        INSERT INTO dbo.KeyName (PartName)
        SELECT @PartName;

        INSERT INTO dbo.EmployeeName (KeyNameID,
                                      EmployeeID)
        VALUES (SCOPE_IDENTITY(), @KeyNameID);
    END;
END;
Run Code Online (Sandbox Code Playgroud)

  • @GuidoG - 我猜这是常见的事情,提问者在尝试变体时将*任何*错误归类为“相同的错误”。他们的“IF”保护版本没有将预期的语句包装在“BEGIN”和“END”中,因此只有第一个“INSERT”受到保护,我认为他们会得到与第二个“INSERT”不同的错误(进入`EmployeeName`) 这是无条件的。 (3认同)