Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
Вот мой триггер:
CREATE TRIGGER tng ON Orders
INSTEAD OF INSERT
AS
BEGIN TRY
BEGIN
DECLARE @Boat int, @i bit, @time date, @time_1 date
SET @i = (SELECT State FROM Boats WHERE id = @Boat)
SET @time_1 = (SELECT Data_pr FROM Boats WHERE id = @Boat)
SET @time = (SELECT TOP 1 Delivery FROM Orders WHERE Boat = @Boat ORDER BY Delivery DESC)
IF (datediff(DAY, @time, @time_1) < 0) AND (datediff(DAY, @time_1, CURRENT_TIMESTAMP) > 31) AND (@i <> 1) BEGIN
RAISERROR('Lodka trebuet pochinki, ili proverki',16,1) END
IF (@time = NULL) BEGIN RAISERROR('Lodka zan''ata',16,2) END
END
END TRY
BEGIN CATCH
SELECT
ERROR_MESSAGE() AS ErrorMessage;
END CATCH

Проблема заключается в том, что не только не выдаётся ошибка, но и не добавляется строка в таблицу. Помогите пожалуйста разобраться где ошибка!
3 дек 11, 17:15    [11701132]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
Voxman
но и не добавляется строка в таблицу.

А где в вашем INSTEAD OF INSERT триггере собственно команда INSERT ?

И еще
Зачем внутри триггера TRY CATCH ?
Как ваш триггер будет обрабатывать добавление нескольких записей одновременно ?
3 дек 11, 17:23    [11701150]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
Glory, я понятия не имею о том, в какой форме я мог бы представить тут INSERT и в каком месте. В начале блоке BEGIN END, и в абстрактном виде INSERT INTO Orders VALUES (@Boat, и т.д.)?

Я TRY CATCH поставил от отчаяния, ибо не обрабатывались ошибки RAISERROR. Нет, обрабатываться будет добавление единственной записи.
3 дек 11, 17:30    [11701164]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
eduard.kasimov
Member

Откуда:
Сообщений: 206
Замечание по синтаксису
автор
IF (@time = NULL)
BOL
Для определения, имеет ли выражение значение NULL, используйте IS NULL или IS NOT NULL вместо сравнения операторов (например = или !=). Сравнение операторов возвращает UNKNOWN, если хотя бы один аргумент или они оба равны NULL.
3 дек 11, 17:34    [11701176]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
eduard.kasimov, спасибо за замечание, впредь буду пользоваться этой корректной формой записи.

Новая версия:
CREATE TRIGGER tng ON Orders
INSTEAD OF INSERT
AS
BEGIN
/* INSERT INTO Orders VALUES (@id, @People, @Boat, @Start, @Finish, @Pay, @Pay_now, @Delivery) */
DECLARE @Boat int, @i bit, @time date, @time_1 date
SET @i = (SELECT State FROM Boats WHERE id = @Boat)
SET @time_1 = (SELECT Data_pr FROM Boats WHERE id = @Boat)
SET @time = (SELECT TOP 1 Delivery FROM Orders WHERE Boat = @Boat ORDER BY Delivery DESC)
IF (datediff(DAY, @time, @time_1) < 0) AND (datediff(DAY, @time_1, CURRENT_TIMESTAMP) > 31) AND (@i <> 1) BEGIN RAISERROR('Lodka trebuet pochinki, ili proverki',16,1) END
IF (@time IS NULL) BEGIN RAISERROR('Lodka zan''ata',16,2) END
END

Сдаётся мне только, что не будет соответствия между @Boat, и тем, что пользователь будет вводить, как значение Boat добавляемой записи.
3 дек 11, 17:38    [11701200]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
Voxman, нет, всё заработало. Выводит ошибку. Т.е. существует соответствие между @Boat и тем, что вводит пользователь, как Boat.

Спасибо всем за деятельное участие в решении моей проблемы!
3 дек 11, 17:41    [11701212]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
Всё же не работает, перепроверил. Решил попробовать AFTER INSERT, но я всё же не понимаю, как мне обратиться к той информации, которую пользователь задаёт через INSERT.

Я посмотрел справку на msdn.microsoft.com, но всё равно не смог найти решение этой проблемы.
3 дек 11, 18:03    [11701267]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
eduard.kasimov
Member

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

можно воспользоваться Constraint. Первый - проверяет условие "Lodka trebuet pochinki, ili proverki", второй - "Lodka zan''ata".
3 дек 11, 18:11    [11701293]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Voxman,

1. чему равен @Baot в этом запросе
SELECT State FROM Boats WHERE id = @Boat
?
2. выбросить все локальные переменные. Лучше в триггере их не использовать.
3. в триггере INSTEAD OF само действие не происходит - надо его вручную там написать. Например, после проверок.
4. поскольку в момент выполнения триггера вставка ещё не произошла, глупо проверять записи самой таблицы.
логичнее это делать в отношении inserted
3 дек 11, 18:35    [11701358]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
eduard.kasimov, знаете, я чем больше читаю о триггерах, тем больше недоумеваю. Неужели нельзя приводить примеры, которые будут ясно иллюстрировать работу триггеров на простых моделях.

Например:

Вот, у меня таблица CREATE TABLE One (id int, name int);

Мне надо создать триггер, который не позволяет добавлять запись, если name > 5 и такого id ещё нет в таблице. Как это будет выглядеть?!
3 дек 11, 18:41    [11701371]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
iap, по идее, @Boat равна тому значению, которое пользователь задаёт при добавлении в таблицу новой строки через INSERT

Я просто нигде не увидел, в явном виде, как обращаться к тем данным, которые пользователь задаёт в INSERT.

2. А я не понимаю, как без них обойтись, везде вместо локальных переменных писать (SELECT TOP 1 ...) или что-то подобное?

3. Добавить после проверок INSERT? Но где я возьму значения введённые пользователем?

4. Понятия не имею, как это сделать...
3 дек 11, 18:47    [11701379]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
Voxman
Мне надо создать триггер, который не позволяет добавлять запись, если name > 5 и такого id ещё нет в таблице. Как это будет выглядеть?!

Для этого существуют constraint-ы - CHECK и UNIQUE
3 дек 11, 18:55    [11701391]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
Voxman
Я просто нигде не увидел, в явном виде, как обращаться к тем данным, которые пользователь задаёт в INSERT.


Вы что читали про триггеры вообще ?
3 дек 11, 18:57    [11701393]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
Glory, я задавал свой вопрос с целью уточнить, как создавать триггеры: попросил проиллюстрировать это на простейшем примере. Мне хотелось бы посмотреть, как в теле триггера можно обращаться к значениям столбцов записи, которые передаются пользователем посредством инструкции INSERT.

Меня не интересует, как в конкретном случае это можно обойти без привлечения триггера. Мне интересно, как создать рабочий триггер.
3 дек 11, 19:00    [11701397]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
eduard.kasimov
Member

Откуда:
Сообщений: 206
Voxman
Например:

Вот, у меня таблица CREATE TABLE One (id int, name int);

Мне надо создать триггер, который не позволяет добавлять запись, если name > 5 и такого id ещё нет в таблице. Как это будет выглядеть?!

Вот как это решается с помощью ограничений:
BEGIN TRANSACTION
GO

CREATE TABLE dbo.One (id INT, name INT) ;
GO

ALTER TABLE dbo.One WITH CHECK ADD CONSTRAINT CK_One_NameIsLessThanSix CHECK (name < 6) ;
GO

INSERT  INTO dbo.One (id, name) VALUES  (1, 1) ;
INSERT  INTO dbo.One (id, name) VALUES  (2, 2) ;
INSERT  INTO dbo.One (id, name) VALUES  (3, 3) ;
INSERT  INTO dbo.One (id, name) VALUES  (4, 4) ;
INSERT  INTO dbo.One (id, name) VALUES  (5, 5) ;
INSERT  INTO dbo.One (id, name) VALUES  (6, 6) ;
GO

ROLLBACK TRANSACTION
GO
3 дек 11, 19:01    [11701398]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
Glory, ряд презентаций, которые мне читали в институте. И справку на MSDN. Там много всего, но простого примера нет.
3 дек 11, 19:02    [11701399]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Voxman
Glory, ряд презентаций, которые мне читали в институте. И справку на MSDN. Там много всего, но простого примера нет.
Использование таблиц inserted и deleted
3 дек 11, 19:06    [11701404]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
eduard.kasimov, это мне в любом случае пригодится, спасибо.
3 дек 11, 19:06    [11701405]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
iap, триггер получился очень объёмистым, нельзя ли его сократить?

CREATE TRIGGER tng ON Orders
INSTEAD OF INSERT
AS
BEGIN
DECLARE @Boat int, @i bit, @time date, @time_1 date, @id int, @People int, @Start date, @Finish date, @Pay bigint, @Pay_now bigint, @Delivery date
SET @Boat = (SELECT Boat FROM inserted)
SET @id = (SELECT id FROM inserted)
SET @People = (SELECT People FROM inserted)
SET @Start = (SELECT Start FROM inserted)
SET @Finish = (SELECT Finish FROM inserted)
SET @Pay = (SELECT Pay FROM inserted)
SET @Pay_now = (SELECT Pay_now FROM inserted)
SET @Delivery = (SELECT Delivery FROM inserted)
SET @i = (SELECT State FROM Boats WHERE id = @Boat)
SET @time_1 = (SELECT Data_pr FROM Boats WHERE id = @Boat)
SET @time = (SELECT TOP 1 Delivery FROM Orders WHERE Boat = @Boat ORDER BY Delivery DESC)
IF (datediff(DAY, @time, @time_1) < 0) AND (datediff(DAY, @time_1, CURRENT_TIMESTAMP) > 31) AND (@i <> 1) BEGIN RAISERROR('Lodka trebuet pochinki, ili proverki',16,1) END
IF (@time IS NULL) BEGIN RAISERROR('Lodka zan''ata',16,2) END
INSERT INTO Orders VALUES (@id, @People, @Boat, @Start, @Finish, @Pay, @Pay_now, @Delivery)
END
3 дек 11, 19:17    [11701415]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
eduard.kasimov
Member

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

из каких соображений выбрали INSTEAD OF триггер?
3 дек 11, 19:23    [11701421]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
eduard.kasimov, если говорить прямо, у меня есть задание: " Создать триггер на добавление новой записи заказа. Проверить, действительно ли яхта, которую пытаются арендовать, на данный момент есть в наличии (нет других действительных договоров по этой яхте) и что ее техническое состояние позволяет сдавать ее в прокат (последняя проверка была сделана после окончания предыдущей аренды и не более месяца назад). Если хотя бы одно из этих условий не выполнено, не создавать запись о заказе, выбрасывать соответствующее исключение. "

Я подумал, что в данном случае хорошо предварительно проверять добавляемую запись, дабы в случае несоответствия вводимых данных и данных из таблиц БД, не добавлять её.
3 дек 11, 19:27    [11701428]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Voxman,
INSERT .... SELECT .... FROM inserted .... WHERE ...
Переменные здесь не нужны.
Правильно заполните промежутки (заполненные многоточиями), и - вуаля!
Или
IF EXISTS(SELECT * FROM inserted WHERE ...) ...
Всё зависит от Вашей стратегии в случае неправильных данных в inserted.
Например, при обнаружении одной ошибки можно вообще отказаться что-либо вставлять.
Но можно вставить всё хорошее, пропустив всё плохое.
Зависит от Вашего замысла.
3 дек 11, 19:29    [11701431]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
iap, попробую перекроить по данному Вами шаблону. Думаю, так будет много лучше.
3 дек 11, 19:32    [11701439]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
eduard.kasimov
Member

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

-- Создать триггер на добавление новой записи заказа. 
ALTER TRIGGER dbo.Orders_CheckOrder ON dbo.Orders
  FOR INSERT
AS
BEGIN

  -- Проверить, действительно ли яхта, которую пытаются арендовать, 
  -- на данный момент есть в наличии (нет других действительных договоров по этой яхте) ...
  IF <условие проверки> 
    BEGIN ;
      RAISERROR('Lodka zan''ata', 16, 2) ;
      ROLLBACK ;
      RETURN ;
    END ;

  -- ... и что ее техническое состояние позволяет сдавать ее в прокат 
  -- (последняя проверка была сделана после окончания предыдущей аренды и не более месяца назад). 
  IF <условие проверки> 
    BEGIN ;
      RAISERROR('Lodka trebuet pochinki, ili proverki', 16, 1) ;
      ROLLBACK ;
      RETURN ;
    END ;
	
END ;
3 дек 11, 19:52    [11701462]     Ответить | Цитировать Сообщить модератору
 Re: Не обрабатываются ошибки в триггере  [new]
Voxman
Member

Откуда:
Сообщений: 28
eduard.kasimov, а как выбрать вторую строку в SELECT. Конкретно тут: (SELECT TOP 1 Delivery FROM Orders WHERE Boat = (SELECT Boat FROM inserted) ORDER BY Finish
DESC)
- Так он мне выдаёт первую строку, а мне надо вторую.
3 дек 11, 20:32    [11701562]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить