Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
Здравствуйте.
Мне необходимо сделать запрос,который будет каждый раз заносить в ячейку "цена" рассчитанные значения которые нужно прописать в триггере.
У меня есть ряд и сеанс. У сеанса есть 3 категории,рядов у нас 20. Для каждого сеанса свой процент,который будет умножен на "стоимость" из таблицы "фильм". Допустим,утренний 10%,дневной 15%,вечерний 18%. С рядами такая же схема. 1-5-ряды 10% 6-10 8% 11-15 7% 16-20 5%. Надеюсь на вашу помощь.
Проще говоря. Когда выбираю ряд и сеанс,у меня в стоимости выводится подсчитанная сумма.
Вот часть кода что удалось составить:
create trigger raz
for insert 
as
begin
declare @a int
set a@ = (select код_билета from inserted)
declare @b int 
set @b = (select  код_фильма from inserted)
declare @c int
set @c = (select стоимость from Фильм where код_фильма = @b)
if (@d="1") then 
update Билет 
set цена = @c*(0,9)
update Билет
set цена = @c*(1,1)

end



Схема таблиц,для полного понимания задачи

К сообщению приложен файл. Размер - 23Kb
7 дек 16, 15:23    [19976747]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8317
fantanol,

почему триггер, а не процедура? Данные выносите вызовом параметризованной процедуры, а не прямым обращением к таблице.
7 дек 16, 15:42    [19976860]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
Sybex
Member

Откуда: Moscow
Сообщений: 117
Когда пишется триггер - всегда нужно предусматривать работу не с одной строкой, а с множеством.
7 дек 16, 15:51    [19976909]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
Sybex
Member

Откуда: Moscow
Сообщений: 117
Вообще я согласен, что запихивать вычисление цены билета в триггер - это не самая здравая мысль и лучше это делать процедурой, хотя бы потому, что в этом случае будет всего лишь одна вставка, а с триггером это сначала insert, потом update. Ну, либо нужно делать INSTEAD OF триггер.
Но для данного подхода, должно быть что-то на подобии:
;WITH CTE
AS
(
    SELECT inserted.код_билета
          ,Фильм.стоимость *
           CASE
               WHEN inserted.ряд <= 5 THEN 1.1
               WHEN inserted.ряд <= 10 THEN 1.08
               WHEN inserted.ряд <= 15 THEN 1.07
               ELSE 1.05
           END *
           CASE inserted.код_сеанса
               WHEN 1 THEN 1.1  --утренний
               WHEN 2 THEN 1.15 --дневной
               ELSE THEN 1.18   --вечерний
           END AS [цена]
      FROM inserted
           JOIN Фильм ON Фильм.код_фильма = inserted.код_фильма
)
UPDATE Билет
   SET цена = CTE.цена
  FROM Билет
       JOIN CTE ON Билет.код_билета = CTE.код_билета;
7 дек 16, 16:42    [19977141]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
Sybex
Вообще я согласен, что запихивать вычисление цены билета в триггер - это не самая здравая мысль и лучше это делать процедурой, хотя бы потому, что в этом случае будет всего лишь одна вставка, а с триггером это сначала insert, потом update. Ну, либо нужно делать INSTEAD OF триггер.
Но для данного подхода, должно быть что-то на подобии:
;WITH CTE
AS
(
    SELECT inserted.код_билета
          ,Фильм.стоимость *
           CASE
               WHEN inserted.ряд <= 5 THEN 1.1
               WHEN inserted.ряд <= 10 THEN 1.08
               WHEN inserted.ряд <= 15 THEN 1.07
               ELSE 1.05
           END *
           CASE inserted.код_сеанса
               WHEN 1 THEN 1.1  --утренний
               WHEN 2 THEN 1.15 --дневной
               ELSE THEN 1.18   --вечерний
           END AS [цена]
      FROM inserted
           JOIN Фильм ON Фильм.код_фильма = inserted.код_фильма
)
UPDATE Билет
   SET цена = CTE.цена
  FROM Билет
       JOIN CTE ON Билет.код_билета = CTE.код_билета;

я так понимаю,это полная процедура?



я вообще навязываюсь на триггер,просто мне предложили такой вариант. вот и получился такой код
если не допустят,то придется делать триггер((
7 дек 16, 18:48    [19977742]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
что с ним не так?

create procedure Цена
WITH CTE
as
begin
(
    SELECT inserted.код_билета
          ,Фильм.стоимость *
           CASE
               WHEN inserted.ряд <= 5 THEN 1.1
               WHEN inserted.ряд <= 10 THEN 1.08
               WHEN inserted.ряд <= 15 THEN 1.07
               ELSE 1.05
           END *
           CASE inserted.код_сеанса
               WHEN 1 THEN 1.1  --утренний
               WHEN 2 THEN 1.15 --дневной
        ELSE THEN 1.18   --вечерний
           END AS [цена]
      FROM inserted
           JOIN Фильм ON Фильм.код_фильма = inserted.код_фильма
)
UPDATE Билет
   SET цена = CTE.цена
  FROM Билет
       JOIN CTE ON Билет.код_билета = CTE.код_билета;
	   end
8 дек 16, 16:43    [19981307]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
londinium
Member

Откуда: Киев
Сообщений: 1193
fantanol,
все с ним не так. таблица INSERTED используется ТОЛЬКО в триггерах
8 дек 16, 17:10    [19981436]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
londinium
fantanol,
все с ним не так. таблица INSERTED используется ТОЛЬКО в триггерах

можете пожалуйста помочь,сделать триггер?
8 дек 16, 17:16    [19981469]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
buven
Member

Откуда:
Сообщений: 792
fantanol
Здравствуйте.
Мне необходимо сделать запрос,который будет каждый раз заносить в ячейку "цена" рассчитанные значения которые нужно прописать в триггере.
У меня есть ряд и сеанс. У сеанса есть 3 категории,рядов у нас 20. Для каждого сеанса свой процент,который будет умножен на "стоимость" из таблицы "фильм". Допустим,утренний 10%,дневной 15%,вечерний 18%. С рядами такая же схема. 1-5-ряды 10% 6-10 8% 11-15 7% 16-20 5%. Надеюсь на вашу помощь.

А что будете делать, когда включится система лояльности для постоянных клиентов с фиксированной скидкой 10% на все сеансы?
Судя по схеме придется заводить по экземпляру каждого билета на каждый сеанс. и потом при покупке умудриться не продать билет на то же место человеку, который не участвует в программе лояльности... С ума сойдешь так...

fantanol
Проще говоря. Когда выбираю ряд и сеанс,у меня в стоимости выводится подсчитанная сумма.

Выводится - ключевое слово. Про процедуру вам говорили видимо в том плане, что цену нужно на лету рассчитывать и отдавать в форнт, а не рассчитывать и хранить. А после покупки фиксировать ту цену, по которой продали со ссылкой на код билета в другой сущности.
Я ничего не перепутал?
8 дек 16, 17:45    [19981587]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8317
buven,

э-э бизнес-логику не программируют на триггерах в сиквеле. Может где-то и пишут, но не здесь.
Если нужны какие-то предварительные вычисления с сохранением результата в таблицах, то используют процедуры.

В данном случае проблему получения корректной информации о билете моно решить не прибегая к вычислениям при сохранении записи о билете, т.к. у билета есть характеристики, которые позволяют вычислить его стоимость запросом.

Например.

Билет:
зал, кресло, время.
Фильм:
зал, время, базовая цена
Скидка:
категория, время, величина скидки
8 дек 16, 17:57    [19981625]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
invm
Member

Откуда: Москва
Сообщений: 9633
Владислав Колосов
э-э бизнес-логику не программируют на триггерах в сиквеле. Может где-то и пишут, но не здесь.
Если нужны какие-то предварительные вычисления с сохранением результата в таблицах, то используют процедуры.
Шо, опять? (с)
Если у вас триггерофобия, это не значит что она у всего остального мира...
8 дек 16, 18:08    [19981654]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
buven
Member

Откуда:
Сообщений: 792
invm
Владислав Колосов
э-э бизнес-логику не программируют на триггерах в сиквеле. Может где-то и пишут, но не здесь.
Если нужны какие-то предварительные вычисления с сохранением результата в таблицах, то используют процедуры.
Шо, опять? (с)
Если у вас триггерофобия, это не значит что она у всего остального мира...


Не придерживаюсь какой то одной стороны, однако было бы интересно узнать реальный пример на триггерах в вашей практике. Если вдруг найдется время - не сочтите за труд.
На моем веку просто триггеры использовались максимум для создания события, по которому дальше уже шла бизнес обработка, когда о результате одного БП нужно было оповестить соседний. Никакой записи результатов расчетов при этом в триггере не производилось.
8 дек 16, 18:32    [19981741]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
buven
А что будете делать, когда включится система лояльности для постоянных клиентов с фиксированной скидкой 10% на все сеансы?
Судя по схеме придется заводить по экземпляру каждого билета на каждый сеанс. и потом при покупке умудриться не продать билет на то же место человеку, который не участвует в программе лояльности... С ума сойдешь так...



у меня нет постоянных клиентов и скидок для них.
у меня есть "стоимость" в таблице фильм. которую нужно каждый раз умножать на "сеанс" и "ряд" из таблицы "билет"для вывода этих расчетов в "цену"
8 дек 16, 18:47    [19981784]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
buven
Member

Откуда:
Сообщений: 792
fantanol
buven
А что будете делать, когда включится система лояльности для постоянных клиентов с фиксированной скидкой 10% на все сеансы?
Судя по схеме придется заводить по экземпляру каждого билета на каждый сеанс. и потом при покупке умудриться не продать билет на то же место человеку, который не участвует в программе лояльности... С ума сойдешь так...



у меня нет постоянных клиентов и скидок для них.
у меня есть "стоимость" в таблице фильм. которую нужно каждый раз умножать на "сеанс" и "ряд" из таблицы "билет"для вывода этих расчетов в "цену"


Дык вам его написали вот тут 19977141 уже.

Хотя судя по коду первого триггера и процедуры - вы не знаете, инструкцию CREATE TRIGGER...
Тут в комментариях пример с CTE на Instead of update.
Вам чуть докрутить и выйдет ваш триггер. Но если уж полезли в эти дебри - придется почитать про триггеры, их типы, какой когда срабатывает и иже с ними... Работы - непочатый край. А все потому, что не хотите править своего же клиента.
Когда сдавать курсовую Помощь с программой ? В разделе "Работа" ходит человек который может вам ее написать и дорассказать то, что забылось с лекций.
8 дек 16, 19:47    [19981975]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
buven
Дык вам его написали вот тут 19977141 уже.

Хотя судя по коду первого триггера и процедуры - вы не знаете, инструкцию CREATE TRIGGER...
Тут в комментариях пример с CTE на Instead of update.
Вам чуть докрутить и выйдет ваш триггер. Но если уж полезли в эти дебри - придется почитать про триггеры, их типы, какой когда срабатывает и иже с ними... Работы - непочатый край. А все потому, что не хотите править своего же клиента.
Когда сдавать курсовую Помощь с программой ? В разделе "Работа" ходит человек который может вам ее написать и дорассказать то, что забылось с лекций.


Есть есть время до сдачи. И платить за этот код уже нет смысла,ведь часть есть. Ладно если бы у меня вообще программы не было. А так осталось лишь его доделать и всё)



сомневаюсь что правильно написал
use 123
go
create trigger TR on T inserted OF UPDATE
AS
WITH CTE AS (
    SELECT inserted.код_билета
          ,Фильм.стоимость *
           CASE
               WHEN inserted.ряд <= 5 THEN 1.1
               WHEN inserted.ряд <= 10 THEN 1.08
               WHEN inserted.ряд <= 15 THEN 1.07
               ELSE 1.05
           END *
           CASE inserted.код_сеанса
               WHEN 1 THEN 1.1  --утренний
               WHEN 2 THEN 1.15 --дневной
               ELSE THEN 1.18   --вечерний
           END AS [цена]
      FROM inserted
           JOIN Фильм ON Фильм.код_фильма = inserted.код_фильма
)
UPDATE Билет
   SET цена = CTE.цена
  FROM Билет
       JOIN CTE ON Билет.код_билета = CTE.код_билета;
update Билет 
go
8 дек 16, 20:44    [19982108]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
invm
Member

Откуда: Москва
Сообщений: 9633
buven
Не придерживаюсь какой то одной стороны
Вот и правильно. Это всего лишь инструменты. Нужно просто знать когда каким можно пользоваться.
buven
однако было бы интересно узнать реальный пример на триггерах в вашей практике.
Да самое простое - обновление сумм документа в шапке при изменении его состава.
Вообще, триггеры изначально и задумывались как средство реализации бизнес-логики на стороне сервера БД.
8 дек 16, 22:25    [19982399]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
Sybex
Member

Откуда: Moscow
Сообщений: 117
fantanol
сомневаюсь что правильно написал

И правильно сомневаетесь. Я говорил о триггере "INSTEAD OF", а не "INSERTED OF".

Ох, я так понимаю это всё учебные примеры?! Так что разжую и в рот положу.
Очень упрощённо! Для таблиц есть два типа триггеров обычные, которые выполняются после операции, и INSTED OF, которые выполняются вместо операции. Т.е. если вы используете первый тип триггера, то сервер сначала выполнит операцию вставки/обновления/удаления записей в таблице, а потом начнёт выполнять код триггера. А если используется второй тип, то код триггера выполняется вместо самой операции вставки/обновления/удаления и в таком случае вам нужно всё это сделать самому в коде триггера.
Если используете первый тип, то триггер будет выглядеть так:
+
CREATE TRIGGER [tr_Билет_ОбновлениеЦены] ON [Билет]
AFTER INSERT
AS
BEGIN
    ;WITH CTE
    AS
    (
        SELECT inserted.код_билета
              ,Фильм.стоимость *
               CASE
                   WHEN inserted.ряд <= 5 THEN 1.1
                   WHEN inserted.ряд <= 10 THEN 1.08
                   WHEN inserted.ряд <= 15 THEN 1.07
                   ELSE 1.05
               END *
               CASE inserted.код_сеанса
                   WHEN 1 THEN 1.1  --утренний
                   WHEN 2 THEN 1.15 --дневной
                   ELSE THEN 1.18   --вечерний
               END AS [цена]
          FROM inserted
               JOIN Фильм ON Фильм.код_фильма = inserted.код_фильма
    )
    UPDATE Билет
       SET цена = CTE.цена
      FROM Билет
           JOIN CTE ON Билет.код_билета = CTE.код_билета;
END

А если второго типа, то так:
+
CREATE TRIGGER [tr_Билет_InsteadOfInsert] ON [Билет]
INSTEAD OF INSERT
AS
BEGIN
    INSERT [Билет]
          ([серия]
          ,[место]
          ,[цена]
          ,[ряд]
          ,[дата_продажи]
          ,[дата_возврата]
          ,[дата_бронирования]
          ,[код_фильма]
          ,[код_сеанса]
          ,[дата_просмотра]
          ,[код_продавца])
    SELECT inserted.[серия]
          ,inserted.[место]
          ,Фильм.стоимость *
           CASE
               WHEN inserted.ряд <= 5 THEN 1.1
               WHEN inserted.ряд <= 10 THEN 1.08
               WHEN inserted.ряд <= 15 THEN 1.07
               ELSE 1.05
           END *
           CASE inserted.код_сеанса
               WHEN 1 THEN 1.1  --утренний
               WHEN 2 THEN 1.15 --дневной
               ELSE THEN 1.18   --вечерний
           END AS [цена]
          ,inserted.[ряд]
          ,inserted.[дата_продажи]
          ,inserted.[дата_возврата]
          ,inserted.[дата_бронирования]
          ,inserted.[код_фильма]
          ,inserted.[код_сеанса]
          ,inserted.[дата_просмотра]
          ,inserted.[код_продавца]
      FROM inserted
           JOIN Фильм ON Фильм.код_фильма = inserted.код_фильма;
END

А вообще вместо всех этих триггеров лучше использовать для вставки и обновления данных хранимые процедуры, но у Вас там вроде уже какой-то клиентский код есть, так что это просто в справочных целях на будущее:
+
CREATE PROCEDURE [Билет_Insert]
     @код_билета        INT  = NULL OUTPUT
    ,@серия             INT  
    ,@место             INT  
    ,@цена              INT  
    ,@ряд               INT  
    ,@дата_продажи      DATE 
    ,@дата_возврата     DATE 
    ,@дата_бронирования DATE 
    ,@код_фильма        INT  
    ,@код_сеанса        INT  
    ,@дата_просмотра    DATE 
    ,@код_продавца      INT  
AS
BEGIN
    INSERT [Билет]
          ([серия]
          ,[место]
          ,[цена]
          ,[ряд]
          ,[дата_продажи]
          ,[дата_возврата]
          ,[дата_бронирования]
          ,[код_фильма]
          ,[код_сеанса]
          ,[дата_просмотра]
          ,[код_продавца])
    SELECT @серия
          ,@место
          ,Фильм.стоимость *
           CASE
               WHEN @ряд <= 5 THEN 1.1
               WHEN @ряд <= 10 THEN 1.08
               WHEN @ряд <= 15 THEN 1.07
               ELSE 1.05
           END *
           CASE @код_сеанса
               WHEN 1 THEN 1.1  --утренний
               WHEN 2 THEN 1.15 --дневной
               ELSE THEN 1.18   --вечерний
           END AS [цена]
          ,@ряд
          ,@дата_продажи
          ,@дата_возврата
          ,@дата_бронирования
          ,@код_фильма
          ,@код_сеанса
          ,@дата_просмотра
          ,@код_продавца
      FROM Фильм
     WHERE Фильм.код_фильма = @код_фильма;

    SET @код_билета = SCOPE_IDENTITY();
END
12 дек 16, 14:56    [19993681]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
Sybex
Ох, я так понимаю это всё учебные примеры?!

Ну как примеры) Курсовые такие

Спасибо за расписанные и подробные примеры


Только мне сейчас еще один понадобился. И на этот раз уже без примера буду. У меня есть дата продажи,просмотра,бронирования и возврата.

Как в триггере можно реализовать запрет на ввод после определенной даты? Допустим нельзя вводить дату продажи выше чем дата просмотра. Дату бронирования выше возврата. Запрет на бронирование за несколько часов до просмотра. Вообще с этими данными можно составить кучу запретов. Но мне хотя бы пример как сделать описанные выше,дальше сам буду стараться.(Находятся они в одной таблице) Буду благодарен.
14 дек 16, 18:39    [20004019]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
buven
Member

Откуда:
Сообщений: 792
fantanol
Sybex
Ох, я так понимаю это всё учебные примеры?!

Ну как примеры) Курсовые такие

Спасибо за расписанные и подробные примеры


Только мне сейчас еще один понадобился. И на этот раз уже без примера буду. У меня есть дата продажи,просмотра,бронирования и возврата.

Как в триггере можно реализовать запрет на ввод после определенной даты? Допустим нельзя вводить дату продажи выше чем дата просмотра. Дату бронирования выше возврата. Запрет на бронирование за несколько часов до просмотра. Вообще с этими данными можно составить кучу запретов. Но мне хотя бы пример как сделать описанные выше,дальше сам буду стараться.(Находятся они в одной таблице) Буду благодарен.


Хватит мучить базу. Тяните на форму, где у вас кнопка "Бронировать", дату начала сеанса, сравнивайте ее с текущей, и если нужно - блокируйте кнопку, чтобы мусорные данные даже не попытались попасть в базу.
14 дек 16, 19:39    [20004184]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
fantanol
Member

Откуда:
Сообщений: 191
buven
fantanol
пропущено...

Ну как примеры) Курсовые такие

Спасибо за расписанные и подробные примеры


Только мне сейчас еще один понадобился. И на этот раз уже без примера буду. У меня есть дата продажи,просмотра,бронирования и возврата.

Как в триггере можно реализовать запрет на ввод после определенной даты? Допустим нельзя вводить дату продажи выше чем дата просмотра. Дату бронирования выше возврата. Запрет на бронирование за несколько часов до просмотра. Вообще с этими данными можно составить кучу запретов. Но мне хотя бы пример как сделать описанные выше,дальше сам буду стараться.(Находятся они в одной таблице) Буду благодарен.


Хватит мучить базу. Тяните на форму, где у вас кнопка "Бронировать", дату начала сеанса, сравнивайте ее с текущей, и если нужно - блокируйте кнопку, чтобы мусорные данные даже не попытались попасть в базу.

у меня задача это всё через триггер сделать(
14 дек 16, 19:59    [20004230]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
Sybex
Member

Откуда: Moscow
Сообщений: 117
fantanol
buven
пропущено...


Хватит мучить базу. Тяните на форму, где у вас кнопка "Бронировать", дату начала сеанса, сравнивайте ее с текущей, и если нужно - блокируйте кнопку, чтобы мусорные данные даже не попытались попасть в базу.

у меня задача это всё через триггер сделать(


Именно через триггер? Не просто "средствами СУБД", а именно "через триггер"? Просто для таких задач (когда данные расположены в одной таблице) используют не триггеры, а ограничения CHECK, которые вешаются на таблицу. Но если в Вас такие условия, то посмотрите по форуму, тут уже всплывали похожие задачи. Например, Триггер на проверку
15 дек 16, 11:12    [20006034]     Ответить | Цитировать Сообщить модератору
 Re: Помощь с триггером  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
fantanol,

instead of trigger, в нём проверка
15 дек 16, 11:16    [20006062]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить