Microsoft SQL Trigger: не удастся ли обновить несколько записей объединения, указывающих на одну и ту же запись? - PullRequest
0 голосов
/ 30 ноября 2010

Справочная информация:

  • У меня есть набор продуктов для каждой пронумерованной недели, начиная с 1.
  • У меня есть «библиотека» товаров, в которой нулевая неделя содержит последний сохраненный товар за любой период времени.
  • У меня есть триггер, который срабатывает при обновлении или вставке, который обновляет элемент «библиотеки» среди вставленных элементов.

Поскольку в одном и том же событии могут присутствовать дубликаты товаров с использованием поля «последовательность», мое объединение создаст для обновления несколько записей, которые нацелены на одну и ту же библиотечную запись.

Некоторые вопросы:

  • Эти мультипликаторы не пройдут команду обновления?
  • Есть ли лучший способ обновить отдельный библиотечный продукт?

код:

-- PK is ID, Week #, and Sequence #
update p set p.name = i.name
from product p join inserted i on
     p.id = i.id and p.week = 0 and p.sequence = 1 

Примечание: «вставлено» может иметь несколько событий. Идентификатор похож на UPC, Неделя - это тождество, а последовательность - на тождество, но начинается с 1 для каждой недели. Вы можете иметь последовательность 2, но не иметь последовательности 1, поскольку они могут удалять продукты.

Пример данных:

ID Неделя Последовательность Имя
12345 1 3 Lego вставлен первым
12345 2 2 Lego Toy вставлен второй
12345 2 3 Lego Toy вставлен второй

Данные результата:

ID Неделя Последовательность Имя
12345 0 1 Lego Toy Был ли "Lego" теперь "Lego Toy"

1 Ответ

2 голосов
/ 30 ноября 2010

В соответствии с этой записью BOL:

Будьте внимательны при указании предложения FROM, чтобы указать критерии для операции обновления.Результаты оператора UPDATE не определены, если он содержит предложение FROM, которое не указано таким образом, чтобы для каждого обновляемого вхождения столбца было доступно только одно значение, то есть если оператор UPDATE не является детерминированным.

Другими словами, если оператор UPDATE использует предложение FROM, которое имеет несколько строк, соответствующих критериям для обновления одной строки, неизвестно, какая строка новых данных будет использоваться.В ваших примерах данных неизвестно, был ли результат обновлен по имени в строке с Sequence=2 или Sequence=3.

Итак, если не имеет значения, какая строка используется для обновления,то, что вы сейчас делаете, будет работать просто отлично.Однако, если это проблема, вам необходимо написать предложения FROM и WHERE вашего обновления, чтобы для каждого элемента возвращалась только одна строка, возможно, что-то вроде следующего:

;with insert2 as (
  select id, week, sequence, name,
         row_number() over(partition by id order by week desc, sequence desc) as [descOrd]
  from inserted
)
update p
set p.name = i.name
from product p
  join insert2 i on p.id = i.id and p.week = 0 and p.sequence = 1
where i.descOrd=1
...