SQL Server Merge Upsert выполняет только обновления и не вставляет

Я хочу записать движение студентов, когда они проводят карточками по двери. Каждый раз, когда представляются идентификатор и имя карты, я хочу проверить, является ли это новой комбинацией, которой еще нет в таблице студентов. Если нет, вставьте новую запись, в которой FirstEntry и LastEntry будут той же датой, а cardid и имя — теми, которые отправлены в соответствующие параметры. Если комбинация уже присутствует, обновите только поле [LastEntry]. На данный момент мой запрос обновляет только существующие записи, что означает, что обновляется только поле [LastEntry]. Для обновления это нормально. Однако он не вставляет новую запись для новой записи. CardID и Name — составные первичные ключи в таблице.

  • Я не хочу использовать метод 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;

Наряду с обновлениями я хочу, чтобы он также вставлял вставки для новых записей.


person user20358    schedule 25.09.2015    source источник
comment
Итак, в чем именно заключается ваш вопрос?   -  person NickyvV    schedule 25.09.2015
comment
ваш выбор делает именно то, что вы ему сказали. если записи с ключом @id, @name нет, то ничего не вставляется.   -  person A ツ    schedule 25.09.2015
comment
Обновил вопрос Ники   -  person user20358    schedule 25.09.2015
comment
@Aツ как мне изменить его, чтобы он соответствовал моим требованиям? Если его там нет, то это должно означать «Нет совпадения», верно? Тогда почему не вставляется?   -  person user20358    schedule 25.09.2015


Ответы (1)


Ваше предложение 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 для вставок).

person sstan    schedule 25.09.2015
comment
Разве я не должен получать здесь старую последнюю запись, а не только значения, которые я отправляю? Я думал, что в случае обновления я смогу получить более старые значения до того, как произошло обновление. Это выполнимо? - person user20358; 25.09.2015
comment
Вы сами решаете, что хотите видеть. Вы можете использовать deleted.<col_name>, чтобы увидеть старое значение (будет null для insert, конечно), и вы можете использовать inserted.<col_name>, чтобы увидеть новое значение, или комбинацию обоих (не забудьте использовать псевдонимы для ваших столбцов, если вы объединяете оба, чтобы избежать двусмысленных имена столбцов на выходе) - person sstan; 25.09.2015