Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Архив форумов ЦИТФорума
Море(!) вопросов - Море(!) ответов
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 
Как правильно задавать вопросы

Как сделать триггер на ограничение ввода данных в SQL Server

 
Перейти:  
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Базы данных
Предыдущая тема :: Следующая тема  
Автор Сообщение
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
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail
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???
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail
vladimir_kg



Зарегистрирован: 05.04.2006
Сообщения: 31

СообщениеДобавлено: Вт Июн 06 2006 07:05    Заголовок сообщения: Ответить с цитатой

Вродебы закончил... новая реализация триггера на обновление для мульти обновления...

ALTER TRIGGER ПроверкаДатыНаВшивостьОбновление ON [dbo].[Table1]
FOR UPDATE
AS
declare @cnt bigint
declare @kolins bigint - кол. реально вставляемых с подходящим условием...
declare @koldel bigint - кол. реально удаляемых с подходящим условием...

SET @cnt = @@rowcount -- сколько записей пытаются изменить???

Select @koldel = count(IDn)
From deleted
Where mydate between dbo.BegDateSsn() and dbo.EndDateSsn()

Select @kolins = count(IDn)
From inserted
Where mydate between dbo.BegDateSsn() and dbo.EndDateSsn()

if (@kolins < @cnt or @koldel < @cnt)
begin
raiserror ('Одна или несколько запписей не могут быть обновлены. Дата вне рабочего диапазона' , 16, -1)
rollback transaction
end


______________________________________
Может кому поможет....
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Базы данных Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2002 phpBB Group
Русская поддержка phpBB

 

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 6608306, ICQ 232284597
Пресс-релизы — pr@citforum.ru
Послать комментарий
Информация для авторов
This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2006 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...