powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Поведение триггера AFTER INSERT,DELETE,UPDATE
26 сообщений из 26, показаны все 2 страниц
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626166
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, коллеги.

Второй день ломаю голову по поводу вот такой задачи -
Есть таблица orders, триггер натравлен на эту таблицу.
Сценарий такой - про добавлении строки в заказы пишется лог в таблицу orders_log и insert двух строк
в вспомогательную таблицу.

Вопрос к знатокам - почему иногда примерно 1000 к 1 в таблице inserted пропадают значения???

К примеру -
1. Создаем заказ (insert into orders)
2. Триггер агрится и начинает выполнение.
3. Достаем значение из inserted и вставляем в лог. Ок.
4. Достаем значение из inserted и вставляем в вспомогательную. Не ок. Строка не создается.

Для понимаю вставлю запрос.

Код: sql
1.
2.
3.
4.
select o.id, dbo.DateToDateStr( o.CREATIONDATETIME), vg.id, vg.* from orders o
left join VG_FIELD_VALUES vg on vg.REF = o.id and FIELDID = 290 
where  CREATIONDATETIME >= 43195.4747560069 
order by o.CREATIONDATETIME desc, o.ID desc



2611730 05.04.2018 15:10:46 84413792 84413792 NewOrder 2611730 0 1 290
2611729 05.04.2018 15:10:45 84413763 84413763 NewOrder 2611729 0 1 290
2611728 05.04.2018 15:10:42 84413735 84413735 NewOrder 2611728 0 1 290
2611726 05.04.2018 15:10:39 NULL NULL NULL NULL NULL NULL NULL
2611727 05.04.2018 15:10:39 84413684 84413684 NewOrder 2611727 0 1 290
2611725 05.04.2018 15:10:36 84413653 84413653 NewOrder 2611725 0 1 290
2611724 05.04.2018 15:10:34 84413625 84413625 NewOrder 2611724 0 1 290

Тело триггера выглядит вот так -

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
SET NOCOUNT ON;
   DECLARE @I BIT = 0, @D BIT = 0, @U BIT = 0, @insert_id bigint = 0, @insert_clientid bigint = 0
    IF EXISTS (SELECT TOP 1 * FROM INSERTED)
    BEGIN
        IF EXISTS (SELECT TOP 1 * FROM DELETED)
        BEGIN    
            SET @U = 1
        END
        ELSE
        BEGIN
            SET @I = 1
        END
    END
    ELSE
    BEGIN
        SET @D = 1
    END  
    IF @D = 1
    BEGIN
        INSERT INTO dbo.ORDERS_log (ChangedID, ChangedOperation)
        SELECT DISTINCT d.ID, 'D'
        FROM deleted d
    END  
    IF @I = 1
    BEGIN
        SELECT @insert_id = i.ID, @insert_clientid = i.clientid FROM inserted i
        INSERT INTO dbo.ORDERS_log (ChangedID, ChangedOperation)
        SELECT @insert_id, 'I'

		insert into VG_FIELD_VALUES (FORMNAME, REF, SVALUE, ENABLED, FIELDID)    
		VALUES
		('NewOrder',@insert_id,CAST(CAST(ROUND(dbo.GetMaxAutoSum(@insert_id), 0) AS VARCHAR(255)) AS TEXT),1,290),
		('NewOrder',@insert_id,CAST(CAST(@insert_clientid ^ 0xdeadee AS VARCHAR(255)) AS TEXT),1,286)
    END 
    IF @U = 1
    BEGIN
        INSERT INTO dbo.ORDERS_log (ChangedID, ChangedOperation)
        SELECT DISTINCT i.ID, 'U'
        FROM inserted i
    END



Определяется тип произведенной операции и производятся действия.
Вот чего я не понимаю почему insert в ORDERS_log выполняется всегда, а следующая вставка 1 к 1000 заканчивается нулами???
Нагрузка на сервер довольно таки большая.
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626168
Фотография Maxx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inserted может содержать больше чем 1 запись
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626177
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxx, не в этом дело. До этого было 3 отдельные вставки без переменных, напрямую из таблицы inserted.
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626199
Гигабайт Мегабайтович Килобайтов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну не волшебство же происходит ))
отсюда два варианта : либо в @insert_id оказывается null, либо в @insert_id оказывается не тот id заказа который вы ожидаете ))
а это может получиться из этого
Код: sql
1.
SELECT @insert_id = i.ID, @insert_clientid = i.clientid FROM inserted i
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626227
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гигабайт Мегабайтович Килобайтов, я из-за этого тему и создал.

я пробовал еще 2 варианта


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
        INSERT INTO dbo.ORDERS_log (ChangedID, ChangedOperation)
        SELECT i.id, 'I' from inserted i

        insert into VG_FIELD_VALUES (FORMNAME, REF, SVALUE, ENABLED, FIELDID)    
	select 'NewOrder', i.id,CAST(CAST(ROUND(dbo.GetMaxAutoSum(@insert_id), 0) AS VARCHAR(255)) AS TEXT),1,290 from inserted i

        insert into VG_FIELD_VALUES (FORMNAME, REF, SVALUE, ENABLED, FIELDID)    
	select  'NewOrder',i.id ,CAST(CAST(i.client_id ^ 0xdeadee AS VARCHAR(255)) AS TEXT),1,286)



Был еще union но он вел себя так же.
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626232
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PisarevskiyRE,

Мне одному кажется странным, что эти данные вставляются
Код: sql
1.
('NewOrder',@insert_id,CAST(CAST(ROUND(dbo.GetMaxAutoSum(@insert_id), 0) AS VARCHAR(255)) AS TEXT),1,290),


а эти нет
Код: sql
1.
('NewOrder',@insert_id,CAST(CAST(@insert_clientid ^ 0xdeadee AS VARCHAR(255)) AS TEXT),1,286)
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626237
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PisarevskiyRE,

а откуда уверенность, что пустые - это не update операции?
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626249
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
blonduser, from inserted строка существует и записывается, следующие 2 оператора пропускается. Повторяюсь это случай 1/1000. И когда это проходит по времени вставки видно что транзакция ожидает чего - то.
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626251
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PisarevskiyRE,

В триггере они у вас выглядят так
Код: sql
1.
2.
3.
4.
		insert into VG_FIELD_VALUES (FORMNAME, REF, SVALUE, ENABLED, FIELDID)    
		VALUES
		('NewOrder',@insert_id,CAST(CAST(ROUND(dbo.GetMaxAutoSum(@insert_id), 0) AS VARCHAR(255)) AS TEXT),1,290),
		('NewOrder',@insert_id,CAST(CAST(@insert_clientid ^ 0xdeadee AS VARCHAR(255)) AS TEXT),1,286)
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626253
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduser,
Что должно пропустится?
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626259
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а покажите скрипт вашей таблички VG_FIELD_VALUES
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626272
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Konst_One, REATE TABLE [dbo].[VG_FIELD_VALUES](
[ID] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[FORMNAME] [varchar](500) NULL,
[REF] [int] NULL,
[SVALUE] [text] NULL,
[ENABLED] [smallint] NULL,
[FIELDID] [int] NULL,
CONSTRAINT [PK__VG_FIELD_VALUES__3A379A64] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [DataFiles]
) ON [DataFiles] TEXTIMAGE_ON [DataFiles]
GO

ALTER TABLE [dbo].[VG_FIELD_VALUES] ADD CONSTRAINT [DF__VG_FIELD___ENABL__3B2BBE9D] DEFAULT ((1)) FOR [ENABLED]
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'Ссылка на Vg_Fields.Id' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'VG_FIELD_VALUES', @level2type=N'COLUMN',@level2name=N'FIELDID'
GO
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626286
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
простите, а какая версия у вас сервера?

Код: sql
1.
select @@version
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626288
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Konst_One,
Microsoft SQL Server 2008 R2 (SP1) - 10.50.2500.0 (X64) Jun 17 2011 00:54:03 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: )
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626290
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вы делаете неверные выводы, потому что анализируете неверный запрос:

Код: sql
1.
2.
3.
4.
5.
6.
7.
select 
   o.id, 
   dbo.DateToDateStr( o.CREATIONDATETIME), 
   vg.id, vg.* 
from orders o left join VG_FIELD_VALUES vg on vg.REF = o.id and FIELDID = 290 
where  CREATIONDATETIME >= 43195.4747560069 
order by o.CREATIONDATETIME desc, o.ID desc



в табличке VG_FIELD_VALUES нет никакой записи с выделенным вами ID
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626303
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а это вы так ищите что нет записи в этой табличке. тогда отбой

зы
вы уверены что у вас удаление не происходит?
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626310
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Konst_One, дык я выделил просто для наглядности в скрине.
Самое простое объяснение идет подряд 3 inserta из inserted.
1, 2, ..,56,..509,..840,.. и рамдомно не пишется, причем если смотреть по id она должна была вставиться гооораздо раньше.

INSERT INTO dbo.ORDERS_log (ChangedID, ChangedOperation)
SELECT @insert_id, 'I'

insert into VG_FIELD_VALUES (FORMNAME, REF, SVALUE, ENABLED, FIELDID)
VALUES
('NewOrder',@insert_id,CAST(CAST(ROUND(dbo.GetMaxAutoSum(@insert_id), 0) AS VARCHAR(255)) AS TEXT),1,290),
('NewOrder',@insert_id,CAST(CAST(@insert_clientid ^ 0xdeadee AS VARCHAR(255)) AS TEXT),1,286)

-- можно так можно через union all можно разбить на 2 отдельных, сути не меняет записи после 1 операции не создаются
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626315
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PisarevskiyRE, извиняюсь за фото. В общем случаи получается такая картина -
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626351
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PisarevskiyRE,

Что возвращает функция dbo.GetMaxAutoSum(@insert_id) ?
Может в ней ошибка?
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626353
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PisarevskiyREPisarevskiyRE, извиняюсь за фото. В общем случаи получается такая картина -
Что вы гадаете с своими запутанными значениями? Кто так отлаживает???

Навставляйте отладочных селектов в триггер, и потом вставляйте в Order, сразу всё увидите.
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626384
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PisarevskiyRE,

1. Никаких переменных в триггере! Ну, разве что переменную с обозначением команда, для которой вызван триггер.
2. С inserted и deleted работать как с таблицами, а не источниками скалярных значений.
3. Не применять @@ROWCOUNT на входе триггера. Только EXISTS(SELECT * FROM inserted UNION ALL SELECT * FROM deleted).
Это на случай, если таблицу будут использовать в MERGE.
4. Забыть о типе TEXT. Вместо него - VARCHAR(MAX).
5. Неплохо бы логгировать только данные, которые изменились.
Хорошо в этом деле зарекомендовала себя конструкция FROM inserted i FULL JOIN deleted d ON i.ID=d.ID WHERE NOT EXISTS(SELECT i.Field1, ... , i.FieldN INTERSECT SELECT d.Field1, ... , d.FieldN),
где ID - первичный ключ.
6. Логгировать можно только из deleted, так как inserted и так лежит в таблице.

Всё настолько просто, что непонятно, что тут можно отлаживать.
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626600
Фотография StarikNavy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PisarevskiyRE,
что вернет запрос?

Код: sql
1.
select * from orders_log where changedID= 2593660
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39626933
PisarevskiyRE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
blonduser, функция возвращает число int.

alexeyvg, спасибо за совет, но это нельзя осуществить так как база прода, на стейджах повторить не давалось.

iap, спасибо, запомнил.

StarikNavy, приложил скрин.

***************************

Проблема решена.
Оказалось все намного тривиальнее.
Строки удаляет сервис после срабатывания триггера обычным delete.
Чудес не бывает. Отменил вызов команды Рен-ТВ :)
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39630235
04cf9f9576a6f15
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iap1. Никаких переменных в триггере! Ну, разве что переменную с обозначением команда, для которой вызван триггер.Почему?

#Хэш=
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39630256
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
04cf9f9576a6f15iap1. Никаких переменных в триггере! Ну, разве что переменную с обозначением команда, для которой вызван триггер.Почему?

#Хэш=Потому что в скалярную переменную можно поместить только одно значение
(обычно мы это и наблюдаем в триггерах новичков),
в то время как inserted и deleted - это таблицы с миллионами строк! (Специально утрирую).
Скалярная переменная провоцирует новичка писать совершенно некорректный код
для обработки таблиц inserted и deleted.
...
Рейтинг: 0 / 0
Поведение триггера AFTER INSERT,DELETE,UPDATE
    #39630327
04cf9f9576a6f15
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iap04cf9f9576a6f15пропущено...
Почему?

#Хэш=Потому что в скалярную переменную можно поместить только одно значение
(обычно мы это и наблюдаем в триггерах новичков),
в то время как inserted и deleted - это таблицы с миллионами строк! (Специально утрирую).
Скалярная переменная провоцирует новичка писать совершенно некорректный код
для обработки таблиц inserted и deleted.Понятно. Это во втором пункте написано. Я уж думал, какие-то особенности работы триггеров с переменными есть, о которых я не знаю.

#Хэш=
...
Рейтинг: 0 / 0
26 сообщений из 26, показаны все 2 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Поведение триггера AFTER INSERT,DELETE,UPDATE
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]