带有 INSERT 语句的 WHERE 子句,WHERE 处的 "Incorrect Syntax" 和 IF NOT EXISTS 运行 无论记录是否存在

WHERE clause with INSERT statement, "Incorrect Syntax" at the WHERE, and IF NOT EXISTS running regardless of if record exists

我有这个 INSERT 查询:

INSERT INTO Appointments (StaffID, CustomerID, TimeSlot, AppDate) 
VALUES (1, 11, 1, DATEADD(day, 1, GETDATE()))
WHERE NOT EXISTS 
    (SELECT * FROM Appointments 
     WHERE StaffID = 1 AND CustomerID = 11 AND TimeSlot = 1 AND AppDate = DATEADD(day, 1, GETDATE()));

然而它说 "Incorrect syntax near the keyword 'WHERE'"

这是非常基本的错误,但不知道是怎么回事。

我也试过使用 IF NOT EXISTS,它没有给出语法错误,但也不起作用,执行插入,即使具有值的记录已经存在:

IF NOT EXISTS 
    (
        SELECT * FROM Appointments 
        WHERE StaffID = 1 AND CustomerID = 11 AND TimeSlot = 1 AND AppDate = DATEADD(day, 1, GETDATE())
    )
    BEGIN
        INSERT INTO Appointments (StaffID, CustomerID, TimeSlot, AppDate) 
        VALUES (1, 11, 1, DATEADD(day, 1, GETDATE()))
END;

值为1、11、1和明天的记录确实100%已经存在,但再次插入。

您不能在 INSERT .. VALUES 语句中指定任何 WHERE 子句。但是您可以使用 INSERT .. SELECT 语句来做到这一点,如下所示。

还有...

The record with the values 1, 11, 1, and tomorrow does 100% already exist, yet inserts it again.

GETDATE() returns 具有小数秒精度的时间戳,这不太可能已经存在于您的 table 中。您可能想使用 DATE 数据类型,例如使用

DATEADD(day, 1, CAST(GETDATE() AS DATE))

插入 .. SELECT

INSERT INTO Appointments (StaffID, CustomerID, TimeSlot, AppDate) 
SELECT 1, 11, 1, DATEADD(day, 1, CAST(GETDATE() AS DATE))
WHERE NOT EXISTS (
  SELECT * 
  FROM Appointments 
  WHERE StaffID = 1 
    AND CustomerID = 11 
    AND TimeSlot = 1 
    AND AppDate = DATEADD(day, 1, CAST(GETDATE() AS DATE))
);

INSERT .. SELECT 使用通用 table 表达式以避免重复

或者,避免多次计算 GETDATE()

WITH ins (StaffID, CustomerID, TimeSlot, AppDate)
  AS (SELECT 1, 11, 1, DATEADD(day, 1, CAST(GETDATE() AS DATE)))
INSERT INTO Appointments (StaffID, CustomerID, TimeSlot, AppDate) 
SELECT ins.StaffID, ins.CustomerID, ins.TimeSlot, ins.AppDate
FROM ins
WHERE NOT EXISTS (
  SELECT * 
  FROM Appointments 
  WHERE StaffID = ins.StaffID 
    AND CustomerID = ins.CustomerID
    AND TimeSlot = ins.TimeSlot 
    AND AppDate = ins.AppDate
);

INSERT .. SELECT 带集合操作

或者,再次更简洁地使用集合操作:

INSERT INTO Appointments (StaffID, CustomerID, TimeSlot, AppDate)
SELECT 1, 11, 1, DATEADD(day, 1, CAST(GETDATE() AS DATE))
EXCEPT
SELECT StaffID, CustomerID, TimeSlot, AppDate
FROM Appointments

合并

实际上,整个 "insert if not exists" 概念也可以使用 MERGE 建模:

MERGE INTO Appointments a
USING (
  SELECT 
    1 StaffID, 
    11 CustomerID,
    1 TimeSlot,
    DATEADD(day, 1, CAST(GETDATE() AS DATE)) AppDate
) ins
ON (
  a.StaffID = ins.StaffID AND 
  a.CustomerID = ins.CustomerID AND 
  a.TimeSlot = ins.TimeSlot AND 
  a.AppDate = ins.AppDate
)
WHEN NOT MATCHED THEN INSERT (StaffID, CustomerID, TimeSlot, AppDate)
  VALUES (ins.StaffID, ins.CustomerID, ins.TimeSlot, ins.AppDate)

你不应该在插入和编写查询时花费时间:

INSERT INTO Appointments (StaffID, CustomerID, TimeSlot, AppDate) 
select 1, 11, 1, DATEADD(day, 1, cast(GETDATE() as date))
WHERE NOT EXISTS 
(SELECT * 
 FROM Appointments 
 WHERE StaffID = 1 AND CustomerID = 11 AND TimeSlot = 1 
 AND AppDate = DATEADD(day, 1, cast(GETDATE() as date))
 )