Size: a a a

2020 March 26

MC

Max Chistyakov in sql_ninja
Как выглядел триггер в первоначальном виде

ALTER TRIGGER rfm_check_list_trI
ON dbo.rfm_check_list
AFTER INSERT
AS
BEGIN
 -- Подразумеваю, что при добавлении новой даты в перечни экстремистов, эта дата автоматически будет приплюсовываться к нужным значениям отдельной таблицы. Добавление в rfm_check_list подразумевается по одной строке.


 DECLARE @extremist_date dbo.DT_DATE;

 SELECT
   @extremist_date =  i.list_date
 FROM inserted AS i

 IF (@extremist_date IS NOT NULL
   AND @extremist_date >= (SELECT MAX(list_date) FROM rfm_check_list WHERE list_kind = 0) )
 BEGIN
   UPDATE vgfv
     SET vgfv.SVALUE += ', ' + dbo.FormatDateTime('dd.MM.yyyy', @extremist_date)
   FROM dbo.VG_FIELD_VALUES as vgfv
   INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
   WHERE vgfv.FIELDID = 338
     AND o.CREATIONDATETIME < @extremist_date
     AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
       OR  o.ORDERSTATUS = 2
       OR  (  o.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
       OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
     );
 END

END


Чтобы понять, в каком месте происходит ошибка, взял в триггере выборку значений с тем же условием, что в UPDATE, и записал их в таблицу отладки chistyakov.error_log. После обновления, взял обновлённые значения, сохранил их в переменную @updated и тоже записал их в таблицу отладки. В итоге стало выглядеть так
ALTER TRIGGER rfm_check_list_trI
ON dbo.rfm_check_list
AFTER INSERT
AS
BEGIN

 DECLARE @updated table (deleted nvarch
@updated table (deleted nvarch
ar(4000), inserted  nvarchar(4000), fieldid int)

 DECLARE @extremist_date dbo.DT_DATE;

 SELECT
   @extremist_date = i.list_date
 FROM inserted AS i

 IF (@extremist_date IS NOT NULL
   AND @extremist_date >= (SELECT MAX(list_
date) FROM rfm_check_list WHERE list_kind = 0) )
 BEGIN
   INSERT INTO chistyakov.error_log (module_name, error_values)
   SELECT OBJECT_NAME(@@PROCID), (
     SELECT
       vgfv.SVALUE as SVALUE_old, vgfv.SVALUE + ', ' + dbo.FormatDateTime('dd.MM.yyyy', @extremist_date) as SVALUE_new, REF
     FROM dbo.VG_FIELD_VALUES as vgfv
     INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
     WHERE vgfv.FIELDID = 338
       AND o.CREATIONDATETIME < @extremist_date
       AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
         OR  o.ORDERSTATUS = 2
         OR  (  o.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
         OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
       )
     FOR XML PATH, R
@PROCID), (
     SELECT
       vgfv.SVALUE as SVALUE_old, vgfv.SVALUE + ', ' + dbo.FormatDateTime('dd.MM.yyyy', @extremist_date) as SVALUE_new, REF
     FROM dbo.VG_FIELD_VALUES as vgfv
     INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
     WHERE vgfv.FIELDID = 338
       AND o.CREATIONDATETIME < @extremist_date
       AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
         OR  o.ORDERSTATUS = 2
         OR  (  o.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
         OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
       )
     FOR XML PATH, ROOT('rows')
   )  ;

    UPDATE vgfv
     SET vgfv.SVALUE += ', ' + dbo.FormatDateT
ime('dd.MM.yyyy', @extremist_date)
   
OUTPUT deleted.SVALUE, inserted.SVALUE, 338 into @updated(deleted, inserted, fieldid)
@updated(deleted, inserted, fieldid)
    FROM dbo.VG_FIELD_VALUES as vgfv
   INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
   WHERE vgfv.FIELDID = 338
     AND o.CREATIONDATETIME < @extremist_date
     AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
       OR  o.ORDERSTATUS = 2
       OR  (  o
.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
       OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
     );
 END

 INSERT INTO chistyakov.error_log (module_name, error_values)
 SELECT OBJECT_NAME(@@PROCID), (
     select deleted, inserted, 1 as updated, fieldid from @updated for xml path, root ('rows')
     )
@PROCID), (
     select deleted, inserted, 1 as updated, fieldid from @updated for xml path, root ('rows')
     )
END
источник

MC

Max Chistyakov in sql_ninja
В итоге, получил два результата: for_update.csv - это  выборка значений с тем же условием, что в UPDATE; actual_updated.csv - это значения из переменной @updated после обновления. Вижу, что обновилось по факту гораздо меньше, чем должно было. В чём может быть дело?
источник

MC

Max Chistyakov in sql_ninja
источник

MC

Max Chistyakov in sql_ninja
источник

MC

Max Chistyakov in sql_ninja
Профайлер во время выполнения не показывает ошибок и откатов транзакций. На таблице VG_FIELD_VALUES, в которой обновляем что нужно, нет триггеров, которые бы откатывали транзакцию, или instead of триггеров, ошибок так же не выдаёт
источник

F

Frankie4Fingers in sql_ninja
Целое тз
источник

G

Gopneg in sql_ninja
да, к нему бы бюджет еще
источник

MC

Max Chistyakov in sql_ninja
я предоставляю максимум информации, когда задаю вопрос, чтобы пропустить вопросы: а тут смотрел, а так смотрел?)
источник

MC

Max Chistyakov in sql_ninja
Max Chistyakov
➡️ Всем привет. Столкнулся с тем, что при обновлении таблицы X через DML триггер на таблице Y, обновляется одна строка в X вместо нескольких тысяч. Трахаюсь с вчерашних семи вечера, пока не вкурил что это. Trigger pitfals в гугле не сообщает о таком поведении.
в первом вопросе описана фабула, которая меня интересует. Всё остальное - вторично)
источник

VS

Vasily S. in sql_ninja
Max Chistyakov
Как выглядел триггер в первоначальном виде

ALTER TRIGGER rfm_check_list_trI
ON dbo.rfm_check_list
AFTER INSERT
AS
BEGIN
 -- Подразумеваю, что при добавлении новой даты в перечни экстремистов, эта дата автоматически будет приплюсовываться к нужным значениям отдельной таблицы. Добавление в rfm_check_list подразумевается по одной строке.


 DECLARE @extremist_date dbo.DT_DATE;

 SELECT
   @extremist_date =  i.list_date
 FROM inserted AS i

 IF (@extremist_date IS NOT NULL
   AND @extremist_date >= (SELECT MAX(list_date) FROM rfm_check_list WHERE list_kind = 0) )
 BEGIN
   UPDATE vgfv
     SET vgfv.SVALUE += ', ' + dbo.FormatDateTime('dd.MM.yyyy', @extremist_date)
   FROM dbo.VG_FIELD_VALUES as vgfv
   INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
   WHERE vgfv.FIELDID = 338
     AND o.CREATIONDATETIME < @extremist_date
     AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
       OR  o.ORDERSTATUS = 2
       OR  (  o.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
       OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
     );
 END

END


Чтобы понять, в каком месте происходит ошибка, взял в триггере выборку значений с тем же условием, что в UPDATE, и записал их в таблицу отладки chistyakov.error_log. После обновления, взял обновлённые значения, сохранил их в переменную @updated и тоже записал их в таблицу отладки. В итоге стало выглядеть так
ALTER TRIGGER rfm_check_list_trI
ON dbo.rfm_check_list
AFTER INSERT
AS
BEGIN

 DECLARE @updated table (deleted nvarch
@updated table (deleted nvarch
ar(4000), inserted  nvarchar(4000), fieldid int)

 DECLARE @extremist_date dbo.DT_DATE;

 SELECT
   @extremist_date = i.list_date
 FROM inserted AS i

 IF (@extremist_date IS NOT NULL
   AND @extremist_date >= (SELECT MAX(list_
date) FROM rfm_check_list WHERE list_kind = 0) )
 BEGIN
   INSERT INTO chistyakov.error_log (module_name, error_values)
   SELECT OBJECT_NAME(@@PROCID), (
     SELECT
       vgfv.SVALUE as SVALUE_old, vgfv.SVALUE + ', ' + dbo.FormatDateTime('dd.MM.yyyy', @extremist_date) as SVALUE_new, REF
     FROM dbo.VG_FIELD_VALUES as vgfv
     INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
     WHERE vgfv.FIELDID = 338
       AND o.CREATIONDATETIME < @extremist_date
       AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
         OR  o.ORDERSTATUS = 2
         OR  (  o.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
         OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
       )
     FOR XML PATH, R
@PROCID), (
     SELECT
       vgfv.SVALUE as SVALUE_old, vgfv.SVALUE + ', ' + dbo.FormatDateTime('dd.MM.yyyy', @extremist_date) as SVALUE_new, REF
     FROM dbo.VG_FIELD_VALUES as vgfv
     INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
     WHERE vgfv.FIELDID = 338
       AND o.CREATIONDATETIME < @extremist_date
       AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
         OR  o.ORDERSTATUS = 2
         OR  (  o.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
         OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
       )
     FOR XML PATH, ROOT('rows')
   )  ;

    UPDATE vgfv
     SET vgfv.SVALUE += ', ' + dbo.FormatDateT
ime('dd.MM.yyyy', @extremist_date)
   
OUTPUT deleted.SVALUE, inserted.SVALUE, 338 into @updated(deleted, inserted, fieldid)
@updated(deleted, inserted, fieldid)
    FROM dbo.VG_FIELD_VALUES as vgfv
   INNER JOIN dbo.ORDERS AS o on o.id = vgfv.REF
   WHERE vgfv.FIELDID = 338
     AND o.CREATIONDATETIME < @extremist_date
     AND (  ( o.ORDERSTATUS in (4, 6)  AND o.RETURNDATETIME >= floor( @extremist_date) )
       OR  o.ORDERSTATUS = 2
       OR  (  o
.ORDERSTATUS = 3  AND o.ORDERSTATUSCHANGEDATETIME >= floor( @extremist_date) )
       OR  (  o.ORDERSTATUS =5  AND o.CLOSEDATETIME >= floor( @extremist_date) )
     );
 END

 INSERT INTO chistyakov.error_log (module_name, error_values)
 SELECT OBJECT_NAME(@@PROCID), (
     select deleted, inserted, 1 as updated, fieldid from @updated for xml path, root ('rows')
     )
@PROCID), (
     select deleted, inserted, 1 as updated, fieldid from @updated for xml path, root ('rows')
     )
END
IF (@extremist_date IS NOT NULL
   AND @extremist_date >= (SELECT MAX(list_date) FROM rfm_check_list WHERE list_kind = 0)) а второе условие может оказаться null, т. е. если все list_kind!=0???
источник

MC

Max Chistyakov in sql_ninja
это сейчас не важно, т.к. ситуация, которую я сейчас рассматриваю, происходит уже когда оба условия уже соблюдены😀
+ я для чата упростил запрос , где определяется @extremist_date , так как в нём была не только эта переменная и они определялись через case в зависимости от list_kind, и для каждой переменной был свой блок begin ... end 😉
источник

VS

Vasily S. in sql_ninja
Max Chistyakov
это сейчас не важно, т.к. ситуация, которую я сейчас рассматриваю, происходит уже когда оба условия уже соблюдены😀
+ я для чата упростил запрос , где определяется @extremist_date , так как в нём была не только эта переменная и они определялись через case в зависимости от list_kind, и для каждой переменной был свой блок begin ... end 😉
и на той таблице триггеры не висят, имеющие возможность быть задействоваными в update? 😁
источник

MC

Max Chistyakov in sql_ninja
не, на таблице, где висит этот триггер, других т. нет
источник

Дt

Дмитрий texnix 🇨🇳 in sql_ninja
подскажите, почему в формуле вычислимого поля может дату не давать использовать?
источник

MC

Max Chistyakov in sql_ninja
у тебя констрэинт указан "по вчерашнее число", например
источник

Дt

Дмитрий texnix 🇨🇳 in sql_ninja
источник

Дt

Дмитрий texnix 🇨🇳 in sql_ninja
есть поле DATABEG - дата
источник

Дt

Дмитрий texnix 🇨🇳 in sql_ninja
а не даёт его никак поставить
источник

DB

Dmitriy Belkin in sql_ninja
Дмитрий texnix 🇨🇳
а не даёт его никак поставить
Почему не дает-то?
источник

DB

Dmitriy Belkin in sql_ninja
Что пишет?
источник