SQL存储过程:如果存在则更新,否则插入

19

好的,我之前在 这里 得到了很多帮助,用于处理一个简单的时间记录系统,但对于我来说它仍然不太行,所以我需要更多的帮助。

我目前正在处理的表包含 6 个列:

  1. clockDate date not null PK
  2. userName varchar(50) not null PK
  3. clockIn time(0)
  4. breakOut time(0)
  5. breakIn time(0)
  6. clockOut time(0)

我认为我已经从上次的问题中找到了如何使用 IF NOT EXISTS INSERT ELSE UPDATE 语句的答案,但现在我试图将其用于存储过程而非普通的查询窗口,却无法成功。

基本上,用户打卡是很简单的。然而,如果用户没有打卡但是他们去吃午饭了,这时语句需要创建一行而不是更新现有的行。下面是我的存储过程:

ALTER PROCEDURE dbo.BreakOut
(
    @userName varchar(50)
)
AS

IF EXISTS (SELECT * FROM Clock WHERE clockDate = GETDATE() AND userName = @userName)
    BEGIN
        UPDATE Clock SET breakOut = GETDATE() 
            WHERE clockDate = GETDATE() AND userName = @userName
    END
ELSE
    BEGIN
        INSERT INTO Clock (clockDate, userName, breakOut) 
            VALUES (GETDATE(), @userName, GETDATE())
    END

这是我的问题... 如果用户当天已经打卡了,我会得到一个主键冲突,因为存储过程仍在尝试运行语句的INSERT部分,而不运行UPDATE行。我已经尝试过使用IF NOT EXISTS反转它,结果相同。如何使IF-ELSE在存储过程中起作用?我正在考虑的方式可行吗,还是必须学习Merge语句?我的计划是从每个工作站上运行简单的Visual Basic程序来运行存储过程。也许我有点难度:( 真希望我的老板肯花钱购买一个时间钟解决方案!

编辑:

谢谢大家的帮助!!我爱上了这个网站,问题迅速得到了回答!!这是我的可用存储过程:

ALTER PROCEDURE dbo.BreakOut
(
    @userName varchar(50)
)
AS

IF EXISTS (SELECT * FROM Clock WHERE DateDiff(dd, GetDate(),clockDate) = 0 AND userName = @userName)
    BEGIN
        UPDATE Clock SET breakOut = GETDATE() 
            WHERE DateDiff(dd, GetDate(),clockDate) = 0 AND userName = @userName
    END
ELSE
    BEGIN
        INSERT INTO Clock (clockDate, userName, breakOut) 
            VALUES (GETDATE(), @userName, GETDATE())
    END
这样合适吗?还能更加改进吗?再次非常感谢大家!!!

1
这是你的 IF 语句 - 不会存在一个时间为 GETDATE() 的记录,因为它返回的也是当前时间!你想要做的是查看该用户在该日期是否已经存在记录。 - dash
4个回答

11

问题可能就在这里:WHERE clockDate = GETDATE()

GetDate返回当前日期和时间,与clockDate不匹配。您可以使用DateDiff来比较日期:

WHERE DateDiff(dd, GetDate(),clockDate) = 0

1
我会把这个标记为答案,但是我没有足够的声望,很抱歉!但是非常感谢!!!! - tmhalbert
到下个月的这一天,这会成为一个问题吗?还是不会?'dd' 是指日期字符串中的日期部分吗? - tmhalbert
2
你可以使用任何一个。它只是检查确保它们是同一天。 - Jim

3

您的问题似乎如下:

假设用户在09:00打卡

可能存在以下记录:

ClockDate    userName    clockIn    breakOut    breakIn    clockOut
12/08/2012   joe         09:00      NULL        NULL       NULL

现在,您的IF语句正在执行以下操作:

SELECT * FROM Clock WHERE clockDate = "20120812 17:24:13" AND userName = @userName

即,该记录不存在。
相反,请尝试这样做:
IF EXISTS (SELECT * FROM Clock  WHERE clockDate = DATEADD(D, 0, DATEDIFF(D, 0, GETDATE())) AND userName = @userName)

您还需要确保将clockDate仅存储为GETDATE()的日期部分,否则,您需要调整查询如下:

IF EXISTS (SELECT * FROM Clock WHERE DATEADD(D, 0, DATEDIFF(D, 0, clockDate)) = DATEADD(D, 0, DATEDIFF(D, 0, GETDATE())) AND userName = @userName)

喜欢你把它分解的方式,谢谢! - tmhalbert

1

0
CREATE PROCEDURE `SP_GENRE_SELECT`(
    IN _Id INTEGER,
      IN _Name VARCHAR(50),
      IN _account VARCHAR (50),
      IN _Password VARCHAR (50),
      IN _LastConnexionDate DATETIME,
      IN _CreatedDate DATETIME,
      IN _UpdatedDate DATETIME,
      IN _CreatedUserId INTEGER,
      IN _UpdatedUserId INTEGER,
      IN _Status TINYINT
    )
BEGIN
      SELECT *
      FROM user
      WHERE Id LIKE IF(_Id IS NULL,'%',CAST(_Id AS VARCHAR(50)))
      AND
      Name LIKE IF(_Name IS NULL,'%',CONCAT('%',_Name,'%'))
      AND
      Account LIKE IF(_Account IS NULL,'%',CONCAT('%',_Account,'%'))
      AND
      LastConnexionDate LIKE IF(_LastConnexionDate IS NULL,'%',CONCAT('%',CAST(LastConnexionDate AS VARCHAR(50),'%')))
      AND
      CreatedDate LIKE IF(_CreatedDate IS NULL,'%',CONCAT('%',CAST(_CreatedDate AS VARCHAR(50),'%')))
      AND
      UpdatedDate LIKE IF(_UpdatedDate IS NULL,'%',CONCAT('%',CAST(_UpdatedDate AS VARCHAR(50),'%')))
      AND
      CreatedUserID LIKE IF(_CreatedUserID IS NULL,'%',CONCAT('%',CAST(_CreatedUserID AS VARCHAR(50),'%')))
      AND
      UpdatedUserID LIKE IF(_UpdatedUserID IS NULL,'%',CONCAT('%',CAST(_UpdatedUserID AS VARCHAR(50),'%')))
      AND
      Status LIKE IF(_Status IS NULL,'%',CAST(_Status AS VARCHAR(50),'%'))

END

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接