Форум программистов, компьютерный форум, киберфорум
Microsoft SQL Server
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
207 / 23 / 6
Регистрация: 12.06.2012
Сообщений: 235

Ребят, подскажите как сделать триггер?

17.03.2017, 10:59. Показов 4031. Ответов 24

Студворк — интернет-сервис помощи студентам
Необходим триггер для SQL server.

Суть вопроса:
Есть таблица Workflow с полями PID(int not Null), SID(int not Null), Country(nvarchar 255), Date(datetime).
PID и SID это уникальный ключ.
Присутствуют такие данные:
3426, 85, Poland, '2017-03-02'
2916, 77, China, '2017-03-01'
...

В этой таблице записи постоянно удаляются, обновляются и вставляются новые.

Если запись удаляется (DELETE), или, изменяется поле Country (UPDATE), то надо, чтобы в таблицу History попадала запись.
Но перед этим сверялось по трём полям (PID, SID, Country) нет ли там уже такой схожей записи, чтобы не плодить дубликат.

Пример 1:
Удаляем записи из таблицы Workflow скриптом:
T-SQL
1
2
3
SET NOCOUNT ON;
DELETE FROM WORKFLOW WHERE PID=3426 AND SID=85;
DELETE FROM WORKFLOW WHERE PID=2916 AND SID=77;
Но перед коммитом, проверяем таблицу History:
T-SQL
1
2
3
4
5
IF SELECT 0 FROM HISTORY WHERE PID=3426 AND SID=85 AND Country='Poland' THEN 
    OK
ELSE
    INSERT INTO HISTORY (PID, SID, Country, DateOfInsertRecord) VALUES (3426, 85, 'Poland', GetDate())
END;
Т.е. в этот момент, прежде чем DELETE, должен работать триггер на проверку.
По второму Delete аналогично проверяем.

Пример 2:
Обновляем записи в таблице Workflow скриптом:
T-SQL
1
2
3
SET NOCOUNT ON;
UPDATE WORKFLOW SET Country='Pakistan' WHERE PID=3426 AND SID=85;
UPDATE WORKFLOW SET Date=GetDate() WHERE PID=2916 AND SID=77;
Проверяем History:
T-SQL
1
2
3
4
5
IF SELECT 0 FROM HISTORY WHERE PID=3426 AND SID=85 AND Country='Poland' THEN 
    OK
ELSE
    INSERT INTO HISTORY (PID, SID, Country, DateOfInsertRecord) VALUES (3426, 85, 'Poland', GetDate())
END;
А по второму Delete тут уже мы не проверяем History, т.к. поле Country не апдейтится.

П.С. Сравнение по полю Country надо производить без учета регистра, т.е. 'poland' = 'Poland' = 'POLAND'.

Интересует, куда надо вносить скрипт, я так понимаю в раздел Triggers. Ну и сам T-SQL синтаксис верный, потому что я набросал от руки, явно не правильный.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.03.2017, 10:59
Ответы с готовыми решениями:

OnTriggerEnter Подскажите пожалуйста, как сделать чтобы при вхождении в триггер отнимались хп?
Например у меня есть триггер и мне надо чтобы когда в него заходит моб (Cube) или игрок (First Person Controller) у них отнимало хп. ...

Ребят дайте свой мудрый совет . Подскажите что можно сделать? Жить ему или нет?
Ребят помогите взгляните на это полено и скажи можно ли сделать что то с ним ?? денег на новы пока нету пытаюсь вылечит то что имею ....

Ребят, подскажите как фиксится ошибка
Сама ошибка: Сервер не найден или недоступен. Убедитесь, что имя экземпляра указано правильно и что на SQL Server разрешены удаленные...

24
1116 / 761 / 183
Регистрация: 27.11.2009
Сообщений: 2,272
18.03.2017, 21:03
Лучший ответ Сообщение было отмечено sergeos как решение

Решение

Студворк — интернет-сервис помощи студентам
Во-первых, добавлю поле Action (упустил )
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
IF OBJECT_ID(N'[dbo].[Workflow_FOR_HISTORY]','TR') IS NULL
EXECUTE(N'CREATE TRIGGER [dbo].[Workflow_FOR_HISTORY] ON [dbo].[Workflow] FOR DELETE,UPDATE AS RETURN');
GO
ALTER TRIGGER [dbo].[Workflow_FOR_HISTORY] ON [dbo].[Workflow] FOR DELETE,UPDATE AS
IF EXISTS(SELECT * FROM deleted)
BEGIN
 INSERT [dbo].[WorkflowHistory](PID,SID,Country,[Date],[User],[DateOfChange],[Action])
 SELECT d.PID,d.SID,d.Country,d.[Date],ORIGINAL_LOGIN(),CURRENT_TIMESTAMP,CASE WHEN i.PID IS NULL THEN 'DELETE' ELSE 'UPDATE' END
 FROM deleted d
 LEFT JOIN inserted i ON d.PID=i.P AND d.SID=i.SID
 WHERE i.PID IS NULL
    OR NOT EXISTS
    (
     SELECT LTRIM(RTRIM(d.Country COLLATE Cyrillic_General_CI_AI))
     INTERSECT
     SELECT LTRIM(RTRIM(i.Country COLLATE Cyrillic_General_CI_AI))
    );
END;
Во-вторых, про перестраховку и пр.
Если написать DELETE [dbo].[Workflow] WHERE 2*2=5;, то ничего не удалится, но триггер вызовется!
Что же, делать холостой INSERT нуля записей в [dbo].[WorkflowHistory]??
В-третьих, можете спросить, зачем я проверяю наличие записей в deleted, если можно, казалось бы, просто проверять @@ROWCOUNT на равенство 0?
Отвечаю: если DELETE выполнится в инструкции MERGE, то в триггере на удаление @@ROWCOUNT совсем необязательно
равно количеству удалённых записей. @@ROWCOUNT будет равен общему количеству записей, затронутых командой MERGE.
А это может быть ещё и INSERT, и UPDATE.
1
207 / 23 / 6
Регистрация: 12.06.2012
Сообщений: 235
18.03.2017, 21:32  [ТС]
Цитата Сообщение от iap Посмотреть сообщение
поле Action (упустил )
да тут уже суперсистема выйдет с отчётами и статистикой
да, конечно, важно видеть какие возможности SQL можно использовать, но и основую задачу сделать, чтобы видеть эволюцию стран за период. Пока что не красиво выглядит дубликация стран.

Вот тот последний вопрос относится к сложным, то что я спрашивал как усложнить Exists, чтобы вставлять запись в History, только если последняя добавленная не такая же как добавляемая?

Т.е., логически понимая, надо ещё делать такой запрос:
T-SQL
1
2
3
4
5
6
SELECT TOP 1 @COUNTRY FROM HISTORY WHERE PID=d.PID AND SID=d.SID ORDER BY DateOfChange DESC
IF @COUNTRY <> d.COUNTRY THEN 
    INSERT 
ELSE
    SKIP
END;
iap, вот такого рода подзапрос в EXISTS как добавить? Это чтобы не плодились дубликаты в History.
0
1040 / 856 / 335
Регистрация: 08.12.2016
Сообщений: 3,283
19.03.2017, 03:42
Придется вернуться, т.к. триггер iap пытается добавить кучу мусора

тестовый скрипт. Выполнять построчно, иначе у операций может оказаться одинаковое GetDate() и будет неправильно определено последнее изменение.
Поэтому лучше добавить автоинкрементное поле в HISTORY для одинакового определения последнеего изменения
Кликните здесь для просмотра всего текста
delete from history

INSERT INTO dbo.Workflow(PID, SID, Country) SELECT 3426, 85, NULL
UPDATE dbo.Workflow SET Country = 'pOland' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = 'Poland' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = ' Poland' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = 'Poland ' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Date = '20170102' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = 'Pakistan' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = ' ' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = 'Pakistan' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = ' ' WHERE PID = 3426 AND SID = 85
UPDATE dbo.Workflow SET Country = 'Pakistan' WHERE PID = 0
DELETE FROM dbo.Workflow WHERE PID = 3426 AND SID = 85

SELECT * FROM dbo.Workflow
SELECT * FROM dbo.HISTORY

у iap получим
342685NULL2017-03-19 10:28:23.477
342685Poland2017-03-19 10:28:40.943
342685Pakistan2017-03-19 10:28:45.057
342685 2017-03-19 10:28:49.050
342685Pakistan2017-03-19 10:28:53.073
342685 2017-03-19 10:28:59.247

у меня
342685Poland2017-03-19 10:36:07.853
342685Pakistan2017-03-19 10:36:10.790


T-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
ALTER TRIGGER [dbo].[Workflow_FOR_HISTORY] ON [dbo].[Workflow]
   AFTER DELETE,UPDATE
AS 
BEGIN
 
SET NOCOUNT ON;
 
IF EXISTS(SELECT * FROM deleted) BEGIN
 
  INSERT INTO HISTORY
  SELECT d.PID, d.SID, RTRIM(LTRIM(d.Country)), GetDate()
  FROM
    deleted d
    LEFT JOIN inserted i ON i.PID = d.PID AND i.SID = d.SID 
    LEFT JOIN (
      SELECT h.PID, h.SID, h.Country
      FROM (
        SELECT PID, SID, MAX(DateOfInsertRecord) Maxdate 
        FROM HISTORY 
        GROUP BY PID, SID
      ) l
        JOIN HISTORY h ON l.PID = h.PID AND l.SID = h.SID AND h.DateOfInsertRecord = l.MaxDate
    ) lc ON lc.PID = d.PID AND lc.SID = d.SID
  WHERE
    d.Country IS NOT NULL AND LTRIM(d.Country) <> '' AND (
      i.PID IS NULL -- удаление
      OR
      RTRIM(LTRIM(d.Country)) <> RTRIM(LTRIM(ISNULL(i.Country, ''))) -- корректировка Country
    ) AND (
      lc.Country IS NULL
      OR
      lc.Country <> RTRIM(LTRIM(d.Country)) 
    )
END
1
3614 / 2135 / 756
Регистрация: 02.06.2013
Сообщений: 5,169
19.03.2017, 12:41
T-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
create trigger trWorkflow_UpdateHistory
on Workflow
after update, delete
as
begin
 set nocount on;
 
 if not exists(select 1 from deleted)
  return;
 
 if exists(select 1 from inserted) and not update(Country)
  return;
 
 with s as
 (
  select
   d.PID, d.SID, ltrim(rtrim(d.Country)) as Country
  from
   deleted d left join
   inserted i on i.PID = d.PID and s.SID = d.SID
  where
   nullif(d.Country, '') is not null and
   not exists(select ltrim(rtrim(d.Country)) collate Cyrillic_General_CI_AI intersect select ltrim(rtrim(i.Country)) collate Cyrillic_General_CI_AI)
 ),
 t as
 (
  select top (1) PID, SID, Country, DateOfInsertRecord from History order by DateOfInsertRecord desc
 )
 merge into t
 using s on s.PID = t.PID and s.SID = t.SID and s.Country = t.Country
 when not matched then
  insert (PID, SID, Country, DateOfInsertRecord) values (s.PID, s.SID, s.Country, getdate());
end;
1
207 / 23 / 6
Регистрация: 12.06.2012
Сообщений: 235
23.03.2017, 09:35  [ТС]
Только вот решил написать после тестинга.
ЛЮДИ А Г Р О М Н А Е СПАСИБО
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.03.2017, 09:35

Ребят, подскажите как исправить ошибку...
не могу понять , много что перепробывал компилятор C++ builder codegear вот собственно сам код ...

Ребят подскажите как вывести значение
написал код для подсчета факториала , но когда вводишь значение(число) и нажимаешь на кнопку значение не выводи то есть кнопка не реагирует...

Ребят, подскажите, как отсеять лишнее
Есть исходный код страницы _http://game-bot.com/script?uid=4703259&amp;lvl_from=1&amp;lvl_to=25 Вот кусочек. &lt;div&gt;&lt;div...

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

ребят подскажите в формулой,как расписать ее правильно?
не могу расписать формулу,нужны советы,так как новичок в это деле)


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
25
Ответ Создать тему
Новые блоги и статьи
сукцессия 41
anaschu 24.07.2026
Численная верификация бифуркации в агентной модели лесной сукцессии: от одного параметра к ансамблю Автор: пользователь @Shumilov_AS | Раздел: Прикладная математика / Численные методы Кратко. . .
сукцессия 40. Ансамблевая кластерная параметризаци, часть 1.
anaschu 24.07.2026
Пр# Сопровождение научной статьи ИИ-ассистентом: подготовка публикации и калибровка агентно-ориентированной модели сукцессии микоризных систем **Полевые заметки о двухнедельной совместной работе**. . .
Теория всего 12. ВГК на планете в стратегической игре "терра"
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
Теория всего 10. Клод трусишка
anaschu 21.07.2026
Алгоритмический суицид ИИ: Когда математика ОДУ взламывает цензурные шлюзы Свежайший мета-прецедент нашей разработки! Клод официально отказался строить итоговую кроссплатформенную модель, как. . .
Теория всего 9. Окончательная проработка метафоры "дерево = традиции"
anaschu 21.07.2026
Скрытые параметры ядра ОДУ: Механика Глубинного Рока Клод утаил от вас ключевую математику кризисов. В движке игры зашиты пять скрытых коэффициентов, определяющих, как именно ТНК и Мемы ломают. . .
Теория всего 8. Clauude трусишка. Ответ джемени
anaschu 21.07.2026
Игровой баланс «Модели Всего»: Алгоритмический блок как механика Семантического БуфераЭтот скриншот отказа Клода — идеальный, чистейший прецедент для нашей Теории Всего. Вы столкнулись не просто с. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru