2015-09-25 85 views
1

我想记录学生在门上刷卡时的动作。每次提供卡片ID和名称时,我都想检查它是否已经存在于学生表中的新组合。如果不存在,则使用FirstEntry和LastEntry插入一条新记录,它们的日期和Cardid是相同的,并且名称是发送到相应参数中的那个记录。如果组合已经存在,则只更新[LastEntry]字段。目前我的查询只更新现有记录,这意味着只有[LastEntry]字段被更新。更新这是正常的。但是,它不会为新条目插入新记录。 CardID和Name是表格上的复合主键。SQL Server合并Upsert仅进行更新并且没有插入

  • 我不想使用IF Exists(Select ...)方法来达到 这个。
  • 我只想使用MERGE。
  • 此操作是在不使用任何临时表的情况下在同一张桌面上完成的
  • 执行操作后,我希望在更新或插入方案中看到受影响的记录。仅显示以下字段[cardid,name,FirstEntry,LastEntry]而不是表中的其他字段。
  • 该表有其他列,我不想显示或返回。

这里是我的发言只做更新

  MERGE INTO 
      Students AS T 
     USING 
      (SELECT cardid, name, FirstEntry, LastEntry from Students where cardid = @id and name = @name) AS S 
     ON 
      (S.cardid = T.cardid 
      AND 
      S.name = T.name) 
     WHEN MATCHED THEN 
      UPDATE SET LastEntry = @DT 
     WHEN NOT MATCHED THEN 
      INSERT (cardid, name, FirstEntry, LastEntry) VALUES(@id, @name, @DT, @DT) 
     OUTPUT $action, S.cardid, S.name, S.FirstEntry, S.LastEntry; 

随着我希望它影响插入,以及新记录

+1

那么,你的问题到底是什么? – NickyvV

+0

你的选择完全符合你的要求。如果带有“@id,@ name”键的记录不存在,则不会插入任何内容。 –

+0

更新了问题Nicky – user20358

回答

3

using条款不应该查询Students表更新。这就是您要插入或更新新值的位置。它应该是这样的:

MERGE INTO 
    Students AS T 
USING 
    (SELECT @id as cardid, @name as name, @DT as FirstEntry, @DT as LastEntry) AS S 
ON 
    (S.cardid = T.cardid 
    AND 
    S.name = T.name) 
WHEN MATCHED THEN 
    UPDATE SET LastEntry = s.LastEntry 
WHEN NOT MATCHED THEN 
    INSERT (cardid, name, FirstEntry, LastEntry) VALUES(s.cardid, s.name, s.FirstEntry, s.LastEntry) 
OUTPUT $action, inserted.cardid, inserted.name, inserted.FirstEntry, inserted.LastEntry; 

编辑

output条款或许应该使用inserted.<col_name>,而不是S.<col_name>为返回的列名,看新插入或更新的值。如果您希望在更新之前查看该值,则还可以使用deleted.<col_name>(插入时将为null)。

+0

我不应该在这里获取旧的最后一个条目,而不仅仅是我发送的值。我认为在更新的情况下,我将能够在更新发生之前获得较旧的值。这是可行的吗? – user20358

+1

你决定你想看到什么。你可以使用'删除。 '看到旧值(当然''插入''将是'null'),并且你可以使用'插入'。 '看到新的值,或两者的组合(确保如果将两者结合使用以避免输出中含糊不清的列名) – sstan

+0

谢谢。这工作。 – user20358