Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.09.2016, 03:01   #1
xxbesoxx
Участник клуба
 
Регистрация: 10.08.2010
Сообщений: 1,389
По умолчанию T-SQL проверка кол-во запись

Здравствуйте , тренирую для себя и не магу понять где допускаю ошибки

-- СУБД: Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64)
-- на пример есть таблица (склад)
Код:
create database MyDB;
-----------------
use MyDB;
-- склад
create table sklad(id_s int identity(1,1) primary key,
                           naimen nvarchar(30), -- Наименование
                           prouzvoditel nvarchar(30), -- Производител
                           kol_vo int, -- кол-во
                           price money-- цена по одну штуку
                          )
есть ещё таблица (продаж) .. на пример
Код:
create table Sale(s_id int identity,
                         s_naimen nvarchar(30),
                         s_prouzvoditel nvarchar(30),
                         s_kol_vo int, -- кол-во
                         s_price money,-- цена по одну штуку
                         s_klad_id int,
                         constraint fk_sale foreign key(s_klad_id ) references sklad(id_s) 
                         on delete cascade
                        )
На складе есть такой товар
Код:
  insert into sklad(naimen, prouzvoditel, kol_vo, price)
  output inserted.*
  values(N'Пива', N'Украина', 40, 3.50),
             (N'Вино', N'Грузинский', 65, 7.80),
             (N'Вино', N'Украина', 80, 6.90),
             (N'Вино', N'Руский', 90, 12.50),
             (N'Кофе', N'Украина', 60, 9.50),
             (N'Кофе', N'Русский', 80, 7.50),
             (N'Чай', N'Грузинский', 80, 8.50),
             (N'Хлеб', N'Украина', 100, 3.65)
Продаж товаров делаю так
Код:
insert into Sale(s_naimen, s_prouzvoditel, s_kol_vo, s_price, s_klad_id)
values(N'Вино', N'Грузинский', 10, 7.50, 2)
При продаже на пример продаю (10-бутылка) вино я хочу что бы отменял кол-во проданных товаров НА кол-во на складе ! Ещё хочу что бы было проверка товар который продаём , такой товар действительно есть на складе ! Если неть то не выполнять это INSERT для этого пишу триггер
Код:
CREATE TRIGGER MyTR_Sales
ON Sale
AFTER INSERT 
AS -- если есть такои товар на складе 
 IF EXISTS (SELECT * 
            FROM inserted I INNER JOIN sklad S 
            ON I.s_naimen=S.naimen
            AND I.s_prouzvoditel=S.prouzvoditel
            )
BEGIN 
 -- тогда отменяем кол-во  sklad -е 
	  UPDATE S  SET kol_vo=kol_vo-I.s_kol_vo
	  FROM  sklad  S INNER JOIN inserted I
	  ON s.naimen=I.s_naimen
	  AND s.prouzvoditel=I.s_prouzvoditel
END
ELSE
-- Если нету такой товар 
IF NOT EXISTS (SELECT * 
               FROM inserted I INNER JOIN sklad S 
               ON I.s_naimen=S.naimen
               AND I.s_prouzvoditel=S.prouzvoditel
               )
BEGIN -- тогда ROLLBACK
    ROLLBACK TRAN;
    RAISERROR(' Такой товар нету на продаже', 16, 1); 
END
Это все нормально работаеть ! Но я хочу чуть-чуть усложнить себе задачу !
На пример: если продаю Вино 10
Код:
insert into Sale(s_naimen, s_prouzvoditel, s_kol_vo, s_price, s_klad_id)
values(N'Вино', N'Грузинский', 10, 7.50, 2)
А на складе нету 10 есть меньше 9 или 8 что бы откатить транзакцию, пишу ещё триггер так
Код:
ALTER TRIGGER MyTR_KOL_VO
ON Sale
AFTER INSERT
AS
declare @Sklad_Moniy money =(SELECT S.kol_vo FROM sklad S
                             INNER JOIN inserted I
                             ON S.naimen=I.s_naimen
                             AND S.prouzvoditel=I.s_prouzvoditel);
declare @Sale_Money money =(SELECT I.s_kol_vo FROM inserted I);
-- вот здесь IF проверка
IF (@Sklad_Moniy-@Sale_Money <=0)
BEGIN
    ROLLBACK TRAN;
    RAISERROR(' Кол-во товаров нету в складе. ля-ля ', 16, 1); 
END
Вот это триггер MyTR_KOL_VO у меня работаеть криво на пример у меня на складе 15-бутылка вино
Код:
select * from sklad where naimen=N'Вино' and prouzvoditel=N'Грузинский';
и продаю 10
Код:
insert into Sale(s_naimen, s_prouzvoditel, s_kol_vo, s_price, s_klad_id)
values(N'Вино', N'Грузинский', 10, 7.50, 2)
insert не выплняется !
Цитата:
Msg 50000, Level 16, State 1, Procedure MyTR_KOL_VO, Line 14
Кол-во товаров который вы хазали нету в складе.! Продаж отменяется
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.
Вопрос : скажите пожалуйста где у меня ощибка триггере MyTR_KOL_VO и как его можно исправить что правильно работал ?
xxbesoxx вне форума Ответить с цитированием
Старый 11.09.2016, 08:36   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

1. Не понятно может ли один и тот же продукт быть на разных складах
2. А с разной ценой на одном складе?
3. Триггера совершенно игнорируют множественную вставку, в том числе и вставку 0 записей
4. Поиск товара идет по всем складам, хотя ид склада есть в продажах
5. В первом триггере зачем-то дублируется EXISTS
6. Во втором триггере скорее всего уже не 15 на складе
7. И в нем же не учитывается возможность NULL для @Sklad_Moniy
8. И не надо там переменных, все одним запросом можно вычислить
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 11.09.2016, 10:52   #3
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

вообще обычно возможность выполнения запроса триггерами, выполняют все же до...запроса(before)
а вот побочные действия, после.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 11.09.2016, 11:26   #4
xxbesoxx
Участник клуба
 
Регистрация: 10.08.2010
Сообщений: 1,389
По умолчанию

Цитата:
1. Не понятно может ли один и тот же продукт быть на разных складах
До пустим только одинь склад
Цитата:
2. А с разной ценой на одном складе?
Яже тренирую , Но если так на пример добавлю
Код:
 IF EXISTS (SELECT * 
            FROM inserted I INNER JOIN sklad S 
            ON I.s_naimen=S.naimen
            AND I.s_prouzvoditel=S.prouzvoditel
            AND I.s_price=S.price
            )
Но это не проблема
Цитата:
3. Триггера совершенно игнорируют множественную вставку
До пустим нету множенство вставка и есть только по одному
Цитата:
5. В первом триггере зачем-то дублируется EXISTS
Что дублируется ?
1. IF EXISTS (SELECT * это же на апдеите
2. IF NOT EXISTS (SELECT * проверяеть есть или нет такой товар при вставке
Цитата:
6. Во втором триггере скорее всего уже не 15 на складе
Есть да 15 и не магу продат 10 вот смотри , выполни
Код:
update sklad set kol_vo= 15 where naimen=N'Вино' and prouzvoditel=N'Грузинский';
А потом почему не магу продать 10 это удивительно
Код:
insert into Sale(s_naimen, s_prouzvoditel, s_kol_vo, s_price, s_klad_id)
values(N'Вино', N'Грузинский', 10, 7.50, 2)
Цитата:
7. И в нем же не учитывается возможность NULL для @Sklad_Moniy
8. И не надо там переменных, все одним запросом можно вычислить
Пробоваль даже без переменных вот так
Код:
ALTER TRIGGER MyTR_KOL_VO
ON Sale
AFTER INSERT
AS
IF  (SELECT S.kol_vo FROM sklad S
     INNER JOIN inserted I
     ON S.naimen=I.s_naimen
     AND S.prouzvoditel=I.s_prouzvoditel) - (SELECT I.s_kol_vo FROM inserted I)<=0
BEGIN
    ROLLBACK TRAN;
    RAISERROR(' Кол-во товаров нету в складе. ля-ля', 16, 1); 
END
Но, все равно не магу продать 10 и на складе есть 15 вот где я допускаю ошибку ?
xxbesoxx вне форума Ответить с цитированием
Старый 11.09.2016, 11:31   #5
xxbesoxx
Участник клуба
 
Регистрация: 10.08.2010
Сообщений: 1,389
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
вообще обычно возможность выполнения запроса триггерами, выполняют все же до...запроса(before)
а вот побочные действия, после.
Я думаю что на данный момент надо проверять "до...запроса" = "до ...insert-ов"

Последний раз редактировалось xxbesoxx; 11.09.2016 в 11:36.
xxbesoxx вне форума Ответить с цитированием
Старый 11.09.2016, 13:24   #6
xxbesoxx
Участник клуба
 
Регистрация: 10.08.2010
Сообщений: 1,389
По умолчанию

Вот так работает правильно триггер MyTR_KOL_VO
Код:
ALTER TRIGGER MyTR_KOL_VO
ON Sale
AFTER INSERT
AS
IF EXISTS (SELECT S.kol_vo, I.s_kol_vo FROM sklad S
           INNER JOIN inserted I
           ON S.naimen=I.s_naimen
           WHERE S.prouzvoditel=I.s_prouzvoditel
           AND S.kol_vo<=0)  
BEGIN
    ROLLBACK TRAN;
    RAISERROR(' Кол-во товаров нету в складе. ля-ля', 16, 1); 
END
Можно тема закрыть .! Спасибо всем за внимание ребята

Последний раз редактировалось xxbesoxx; 11.09.2016 в 13:26.
xxbesoxx вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
sql запрос. проверка значения II_Dimit_II БД в Delphi 7 03.06.2013 09:11
Проверка условия. sql запрос II_Dimit_II БД в Delphi 1 31.05.2013 03:08
(ADO,SQL) Проверка на не существующую запись в дочерней таблице Never74 БД в Delphi 1 23.02.2012 16:43
Проверка есть ли такая запись в таблице Uxas Помощь студентам 6 20.02.2011 19:55
ограничение кол-ва SQL запросов в BDE ?!!! Qdesnik БД в Delphi 1 15.05.2009 17:24