25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
1

Тригер, проверяющ. есть ли такой ID и если есть обновляющий его, если нет - добавляющий

02.06.2013, 02:34. Показов 1499. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Сабж.
В MSSQL нуб.

Есть ситуация. Добавляю товар из каталога поставщика в каталог магазина.
Может быть такое, что мы заказываем один и тот же товар второй раз. Нужно написать триггер учитывающий этот момент.
Задачи триггера:
1. Добавление/изменение записи.
2. Обновления количества в таблице каталога поставщика.

Я понимаю, что триггер должен быть по событию INSERT. Как я понял понятия "перед" или "после" нету, есть только после -AFTER. В других БД есть ON DUPLICATE KEY, как я понял, здесь такого нету. будем пробовать биться без этой фишки.

Вот что я наискал, надумал и т.п. Код не мой, я в нем разбирался, изменял. По нему будут вопросы.
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
CREATE TRIGGER insert_trigger
ON OrdersGoodsSup FOR INSERT
AS
DECLARE @count INT, @id INT
IF @@ROWCOUNT=1
--в таблицу Сделка добавляется запись 
--о поставке товара
BEGIN
--если записи о товаре еще нет,
--добавляется соответствующая запись
--в таблицу OrdersGoodsSup
  IF NOT EXISTS ( SELECT * FROM inserted i, SuppliersGoods S WHERE S.ID=i.GoodID )
      INSERT INTO OrdersGoodsSup(GoodID, Count) values (-- что тут писать?--)
  ELSE
--если запись о товаре уже была в таблице 
--OrdersGoodsSup, то определяется код и количество 
--товара из добавленной в таблицу OrdersGoodsSup записи
  BEGIN
    SELECT @id=i.GoodID, @count=i.Count
    FROM SuppliersGoods S, inserted i
    WHERE S.ID=i.GoodID
--и производится изменения количества товара в
--таблице OrdersGoodsSup
    UPDATE OrdersGoodsSup
    SET Count=Count+@count
    WHERE OrdersGoodsSup.GoodID=@id
  END
 
  UPDATE SuppliersGoods set Count = Count - @count where SuppliersGoods.ID = @id
END
- Какой смысл в переменной inserted?
Дальше по строкам:
5. @@ROWCOUNT=1. Сама глобальная переменная - считает количество записей в таблице.
а) Хочу уточнить. Количество записей во всей таблице или именно с этим ID?
б) Еще момент. =1 почему? потому что у нас триггер срабатывает после и у нас уже добавлена запись получается?
13. Не очень понимаю, что нужно писать в values. В других бд видел что-то вроде "new.xxxx", где xxx название поля - это и было значением добавленным. нужно вставить что-то из inserted?
18-27 правильно ли тут поступаю? сюда попали по неуд условию, значит здесь записи есть и мы их обновляем. так сделал?
29. правильно ли обновляю количество товара у поставщика.

может вопросы и тупые, но проверить этого не могу из-за того, что не знаю что писать в values в 13 строке.

есть желающие выручить?)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.06.2013, 02:34
Ответы с готовыми решениями:

триггеры на проверку если запись есть то пропустить если нет то добавить...
есть триггер но он работает только при добавлении одной записи.... мне нужно что бы он просматривал...

Обработка символьных данных. Yes, если есть символ в строке и NO если его нет
Здравствуйте! Помогите решить задачу: Если в данный текст входит любая из букв слова key,...

Если есть форма и есть событие, а процедуры, его обрабатывающей нет в исходниках, то как это событие обрабатывается?
Друзья! Изучаю синтаксис дельфи. Ну то есть к примеру такой код: procedure...

Машина Тьюринга: Удалить из слова Р его второй символ, если такой есть
Машина Тьюринга 1. А={a,b}. Удалить из слова Р его второй символ, если такой есть. 2. A={a,b,c}....

9
1923 / 1159 / 422
Регистрация: 31.05.2012
Сообщений: 4,096
02.06.2013, 14:33 2
1. inserted - временная таблица с вставляемыми записями
2. @@ROWCOUNT=1 - триггер для групповой вставки работать не будет, а только для вставки по одной записи
3. value - список вставляемых значений - констант и выражений. inserted пользоваться можно как обычной таблицей
заменил бы на INSERT INTO OrdersGoodsSup(GoodID, Count) SELECT i.GoodID,i.Count FROM inserted i
4. Count - неудачное название поля из ключевых слов T-SQL
5. Значение @count не определено в при вставке, поэтому в последнем UPDATE будут проблемы
0
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
02.06.2013, 21:02  [ТС] 3
Цитата Сообщение от Аватар Посмотреть сообщение
@@ROWCOUNT=1 - триггер для групповой вставки работать не будет, а только для вставки по одной записи
как понять групповой? я и буду вставлять по одной записи.

в любом случае - не получается пока. давайте с другово бока.

пока что уберем update количества в SuppliersGoods
у меня есть таблица SuppliersGoods, есть таблица OrdersGoodsSup. Из первой во вторую добавляются товары. Вторая это корзина.
SuppliersGoods - ID, Name, Count, Price
OrdersGoodsSup - ID, GoodID, Count, Price, OrderID (связь с номером заказа)
Вторая связана с первой по GoodID.

Мне необходимо, чтобы при первом добавлении записи в OrdersGoodsSup она просто добавлялась, а при повторном просто увеличивалось количество.

Например:
SuppliersGoods
+----+------+------+------+
| ID |Name | Count| Price |
+----+------+------+------+
| 5 |Good1| 50 | 500 |
+----+------+------+------+
| 6 |Good2| 80 | 500 |
+----+------+------+------+

OrdersGoodsSup
+----+-------+------+------+
| ID |GoodID | Count| Price |
+----+-------+------+------+
| | | | |
+----+-------+------+------+

это состояние в первый момент.

первое добавление:
T-SQL
1
insert into OrdersGoodsSup (GoodID, Count, Price) values (5, 10, 500)
SuppleirsGoods - не меняется
OrdersGoodsSup
+----+-------+------+------+
| ID |GoodID | Count| Price |
+----+-------+------+------+
| 1 | 5 | 10 | 500 |
+----+-------+------+------+

T-SQL
1
insert into OrdersGoodsSup (GoodID, Count, Price) values (5, 20, 500)
SuppleirsGoods - не меняется
OrdersGoodsSup
+----+-------+------+------+
| ID |GoodID | Count| Price |
+----+-------+------+------+
| 1 | 5 | 30 | 500 |
+----+-------+------+------+
ТАК ДОЛЖНО БЫТЬ.

У меня работает триггер неправильно. У меня после двух таких запросов содержимое таблицы OrdersGoodsSup будет таким.
+----+-------+------+------+
| ID |GoodID | Count| Price |
+----+-------+------+------+
| 1 | 5 | 10 | 500 |
+----+-------+------+------+
| 2 | 5 | 30 | 500 |
+----+-------+------+------+
Это неправильно. Должно обновиться.
Мало того, если в таблице OrdersGoodsSup были такие же товары, заканные несколькими заказами ранее - они обновятся. То есть для них триггер срабатывает. Я думаю это изза того, что мы не учитываем OrderID.

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
ALTER TRIGGER [dbo].[insert_trigger]
ON [dbo].[OrdersGoodsSup] FOR INSERT
AS
DECLARE @count INT, @id INT
SELECT @id=i.GoodID, @count=i.Count
FROM SuppliersGoods S, inserted i
WHERE S.ID=i.GoodID
IF @@ROWCOUNT=1
--в таблицу Сделка добавляется запись 
--о поставке товар
BEGIN
--если записи о товаре еще нет,
--добавляется соответствующая запись
--в таблицу OrdersGoodsSup
  IF NOT EXISTS ( SELECT * FROM inserted i, SuppliersGoods S, SuppliersOrders O WHERE S.ID=i.GoodID and i.OrderID = O.ID)
      INSERT INTO OrdersGoodsSup(OrderID, GoodID, Count) SELECT i.OrderID, i.GoodID,i.Count FROM inserted i
  ELSE
--если запись о товаре уже была в таблице 
--OrdersGoodsSup, то определяется код и количество 
--товара из добавленной в таблицу OrdersGoodsSup записи
  BEGIN
--и производится изменения количества товара в
--таблице OrdersGoodsSup
    UPDATE OrdersGoodsSup
    SET Count=Count+@count
    WHERE OrdersGoodsSup.GoodID=@id
  END
END
что я делаю не так?
0
3499 / 2083 / 742
Регистрация: 02.06.2013
Сообщений: 5,078
03.06.2013, 00:08 4
Цитата Сообщение от VladSharikov Посмотреть сообщение
что я делаю не так?
Если кратко - все.
Начнем с того, что триггер for (after) insert срабатывает после соответствующей инструкции. Т.е., при попытке добавить в корзину позицию, которая там уже есть, вы получите в лучшем случае, если у вас хотя-бы нужные ограничения есть на таблице, соответствующую ошибку, в худшем, - бардак в таблице.
Триггер должен быть instead of insert и в нем использовать инструкцию merge, если версия сервера позволяет.
0
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
03.06.2013, 00:40  [ТС] 5
invm, о, о, о)) намного ближе к теме. очень похоже на ON DUPLICATE KEY

T-SQL
1
2
3
4
5
6
7
8
    MERGE OrdersGoodsSup AS ogs 
    USING inserted AS i 
    ON ogs.GoodID = i.GoodID
    WHEN MATCHED THEN
    --UPDATE SET column1 = value1 [, column2 = value2 ...]
 
    WHEN NOT MATCHED THEN
    --INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...
первое. ругается на 3 строчку. говорит, что условие не является логическим (короче не true/false). почему?
второе. я правильно подобрал table_target - OrdersGoodsSup и table_source - inserted?

по идее я сравниваю то, что мы пытаемся вставить с тем, что уже вставлено. и если есть соответствие по этим полям, то MATCHED, если нет, то NOT. почему не работает?
SQL Server 2012.
0
3499 / 2083 / 742
Регистрация: 02.06.2013
Сообщений: 5,078
03.06.2013, 09:27 6
VladSharikov, покажите полностью оригинальный текст триггера.
0
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
03.06.2013, 18:17  [ТС] 7
invm, вы сказали использовать merge, я начал делать заново. это не чей-то скрипт. это я сам уже делаю и походу спрашиваю у вас.
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
ALTER TRIGGER [dbo].[insert_trigger]
ON [dbo].[OrdersGoodsSup] 
INSTEAD OF INSERT
AS
MERGE OrdersGoodsSup AS ogs 
USING inserted AS i 
ON ogs.GoodID = i.GoodID
WHEN MATCHED THEN
--UPDATE SET column1 = value1 [, column2 = value2 ...]
 
WHEN NOT MATCHED THEN
--INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...
0
3499 / 2083 / 742
Регистрация: 02.06.2013
Сообщений: 5,078
03.06.2013, 18:24 8
Ну так зачем вы merge комментариями покорежили? Напишите ее полностью, согласно синтаксису.
0
25 / 25 / 7
Регистрация: 02.12.2010
Сообщений: 824
03.06.2013, 18:52  [ТС] 9
invm, ой красота вообще))) спасибо вам огромное)))

не думал, что из-за этого будут проблемы! не встречал такого никогда. все заработало!

Вот правильный триггер:
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
ALTER TRIGGER [dbo].[insert_trigger]
ON [dbo].[OrdersGoodsSup] 
INSTEAD OF INSERT
AS
MERGE OrdersGoodsSup AS ogs 
USING inserted AS i 
ON ogs.GoodID = i.GoodID and ogs.OrderID = i.OrderID
WHEN MATCHED THEN
UPDATE SET ogs.Count = ogs.Count + i.Count
WHEN NOT MATCHED THEN
INSERT (GoodID, Count, OrderID) VALUES (i.GoodID, i.Count, i.OrderID);
GO
0
0 / 0 / 0
Регистрация: 06.10.2014
Сообщений: 24
12.11.2015, 08:44 10
VladSharikov,
Доброго Вам дня..
Вижу Вы сами разбирались с "лексикой" SQL. Я тоже только начинаю изучать. Подскажите - как правильно задать событие, чтобы триггер сработал? При чём на одной базе он работал, а на созданной вновь не хочет. Понимаю, что какая-то ошибка, только не могу найти где.. Select-ы для баз работают.. А триггер должен удалять записи об авторах, книг которых не осталось в библиотеке. Вот он сам:
T-SQL
1
2
3
4
5
6
7
8
create TRIGGER Del_trig 
 ON dbo.Books
 instead of DELETE
 AS 
 delete from dbo.Books_Authors where Book_Kod in(select kod from deleted)
 delete from dbo.Books_Readers where Book_Kod in(select kod from deleted)
 delete from dbo.books where Kod in(select kod from deleted)
 delete from dbo.Authors where Kod not in(select Author_Kod from dbo.Books_Authors)
0
12.11.2015, 08:44
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.11.2015, 08:44
Помогаю со студенческими работами здесь

Машина Тьюринга. Удалить из слова P его третий символ, если такой есть
A={a,b}. Удалить из слова P его третий символ, если такой есть.

Дан массив X(N). Найти наибольший элемент и поменять его местами с первым положительным элементом, если такой есть
Дан массив X(N). Найти наибольший элемент и поменять его местами с первым положительным элементом,...

Если в диапазоне есть время больше указанного,то 500,если нет - 0
Вопрос связан с расчетом зарплаты. Есть отдельно табель учета времени прихода/ухода, на сколько...

Создание системной переменной если её нет и удаление если есть (setenv)
Нужен своеобразный переключатель определенной системной переменной с помощью утилиты setenv. Суть...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru