vladimir_kg
Зарегистрирован: 05.04.2006 Сообщения: 31
|
Добавлено: Вс Июн 04 2006 17:49 Заголовок сообщения: Как сделать триггер на ограничение ввода данных в SQL Server |
|
|
Задача состоит в следущем. Есть таблица в которую вводятся данные среди которых присутствует дата.
Условие: дата должна входить в определенный период который указан в другой таблице. Задача на первый взгляд не тривиальная. Но мне пришлось несколько повозиться чтобы я сумел ее решить.
Со вставкой ни каких проблем проверяем вставляемые данные таблица inserted, если дата подходит указанному периоду тогда вставляем данные:
Примечание функция inSession – проверяет входит ли дата в указанный период.
CREATE TRIGGER ПроверкаДатыВставка ON [dbo].[Table1]
FOR INSERT
AS
Declare @mydate datetime
Select @mydate = mydate
From inserted
if (dbo.inSession(@mydate) = 0)
begin
raiserror ('Нельзя обновить данные, дата вне рабочего периода.', 16, -1)
rollback transaction
end
С удалением тоже ни каких проблем, проверяем таблицу deleted перед тем как удалить данные, если дата в рабочем периоде т.е. то без проблем удаляем, если нет rollback-чим транзакцию…
CREATE TRIGGER ПроверкаДатыУдаление ON [dbo].[Table1]
FOR DELETE
AS
Declare @mydate datetime
Select @mydate = mydate
From deleted
if (dbo.inSession(@mydate) = 0)
begin
raiserror ('Дата вне рабочего периода. Нет доступа на удаление', 16, -1)
rollback transaction
end
Самое интересно с обновлениме таблицы… Вы скажите ни каких проблем подобно вставке… Да я тоже так думал, но…
Но сначала задача:
Нужно чтобы нельзя было обновлять данные если они не входят в текущий период, а также нельзя было обновлять данные в текущем периоде на такие что они после обновления переходили в другой период.
Итак первая реализация триггера:
CREATE TRIGGER ПроверкаДатыНаВшивостьОбновление1 ON [dbo].[Table1]
for UPDATE
AS
Declare @mydate datetime -- дата которую обновляют
declare @insDate datetime -- дата которую пытаются вставить
declare @currentIDn bigint -- код обновляемой записи (ключевое поле)
Select @mydate = Table1.mydate,
@insDate = inserted.mydate, @currentIDn = inserted.IDn
From Table1, inserted
Where Table1.IDn = inserted.IDn
-- проверка текущей даты и проверка вставляемой даты
-- ни та ни другая должны быть в текущем периоде, если не так – ерор.
if (dbo.inSession(@mydate) = 0 or dbo.inSession(@insDate) = 0)
begin
raiserror ('Дата вне рабочего периода.', 16, -1)
rollback transaction
end
Да не тут то было… Этот триггер работает только в одном случае если таблица не имеет связей… Если же таблица имеет подчиненную таблицу то все пропало данный триггер уже не срабатывает, не знаю в чем тут дело, но факт остается фактом.
Вторая реализация данного триггера. Здесь в место ключевого слова FOR, используется INSTEAD OF.
FOR – триггер срабатывает до обновления, добавления или удаления.
INSTEAD FOR – триггер заменяет те же самые действия, т.е. нам придется позаботится о заменяемом действии в моем случае обновлении записи…
И так вот реализация триггера, этот триггер не подводит даже если таблица имеет связи, а также он не намного сложнее предыдущего, добавлено только одно действие обновление данных в ручную
CREATE TRIGGER ПроверкаДатыНаВшивостьОбновление2 ON [dbo].[Table1]
instead of UPDATE
AS
Declare @mydate datetime
declare @insDate datetime
declare @currentIDn bigint
Select @mydate = Table1.mydate,
@insDate = inserted.mydate,
@currentIDn = inserted.IDn
From Table1, inserted
Where Table1.IDn = inserted.IDn
if (dbo.inSession(@mydate) = 0 or dbo.inSession(@insDate) = 0)
begin
raiserror ('Дата вне рабочего периода.', 16, -1)
rollback transaction
end
else
begin
UPDATE Table1
SET Table1.mydate = inserted.mydate,
Table1.other = inserted.other
-- единственно не удобно при большом количество столбцов
FROM inserted, Table1
WHERE inserted.IDn = Table1.IDn
commit transaction
end
Внимание вопрос.
Уважаемые знатоки, ответьте в чем я не прав, и как сделать по проще но чтобы все работало???
Владимир qsmart@mail.ru |
|
vladimir_kg
Зарегистрирован: 05.04.2006 Сообщения: 31
|
Добавлено: Пн Июн 05 2006 06:47 Заголовок сообщения: |
|
|
Лучше поздно чем никогда.
Порылся я в инете http://sql.softmatics.ru/ и нашел, в разделе посвященом триггерам...
при обновлении записи, старые записи попадают в таблицу deleted, а новые в таблицу inserted
вот новая реализация триггера....
CREATE TRIGGER ПроверкаДатыНаВшивостьОбновление ON [dbo].[Table1]
FOR UPDATE
AS
Declare @mydate datetime
declare @insDate datetime
Select @mydate = deleted.mydate,
@insDate = inserted.mydate
From deleted, inserted
Where deleted.IDn = inserted.IDn
if (dbo.inSession(@mydate) = 0 or dbo.inSession(@insDate) = 0)
begin
raiserror ('Дата вне рабочего периода.', 16, -1)
rollback transaction
end
Но теперь еще одна проблема.....
Она не работает для мульти обновления.... или работает но не правильно...
Есть ли еще ссылки, на сайты посвященые разработке приложений в SQL server 2000??? |
|