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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 03.05.2012, 14:54   #1
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
Вопрос Реализация и работа с триггерами

Здравствуйте! Ради спортивного интереса разбираюсь с реализацией триггеров в SQL и передо мной встала огромная проблема.
База создается с помощью следующего SQL-запроса:
Код:
/*
Created: 03.05.2012
Modified: 03.05.2012
Model: Microsoft SQL Server 2008
Database: MS SQL Server 2008
*/

-- Create tables section -------------------------------------------------

-- Table Сотрудники

CREATE TABLE [Сотрудники]
(
 [ФИО] Varchar(100) NOT NULL,
 [Уровень доступа] Int NULL,
 [Наименование группы] Varchar(100) NULL,
 [ФИО_админа] Varchar(100) NULL
)
go

-- Add keys for table Сотрудники

ALTER TABLE [Сотрудники] ADD CONSTRAINT [Key1] PRIMARY KEY ([ФИО])
go

-- Create triggers for table Сотрудники

CREATE TRIGGER [Update_Trigger]
  ON [Сотрудники]
  AFTER UPDATE
  AS


DECLARE @фио_ins varchar(100)
    DECLARE @фио_del varchar(100)

SELECT @фио_ins=[ФИО] FROM Inserted
SELECT @фио_del=[ФИО] FROM Deleted

UPDATE
        [Группы пользователей]
            SET
                [ФИО_админа]= @фио_ins
            WHERE 
                [ФИО_админа]=@фио_del
go

-- Table Группы пользователей

CREATE TABLE [Группы пользователей]
(
 [Наименование группы] Varchar(100) NOT NULL,
 [ФИО_админа] Varchar(100) NOT NULL
)
go

-- Add keys for table Группы пользователей

ALTER TABLE [Группы пользователей] ADD CONSTRAINT [Key2] PRIMARY KEY ([Наименование группы],[ФИО_админа])
go

-- Create relationships section ------------------------------------------------- 

ALTER TABLE [Группы пользователей] ADD CONSTRAINT [Relationship21] FOREIGN KEY ([ФИО_админа]) REFERENCES [Сотрудники] ([ФИО]) ON UPDATE NO ACTION ON DELETE NO ACTION
go

ALTER TABLE [Сотрудники] ADD CONSTRAINT [Relationship22] FOREIGN KEY ([Наименование группы], [ФИО_админа]) REFERENCES [Группы пользователей] ([Наименование группы], [ФИО_админа]) ON UPDATE NO ACTION ON DELETE NO ACTION
go
Созданный триггер Update_Trigger создан для того, чтобы при изменении строки в таблице "Сотрудники", изменялись и соответствующие данные и в таблице "Группы пользователей".
Вставляем в таблицу "Сотрудники" строку с помощью запроса:
Код:
INSERT INTO dbo.[Сотрудники] ([ФИО], [Уровень доступа])
		VALUES ('Иванов', '22')
Все отлично вставилось. Теперь вставляю строку в таблицу "Группы пользователей":
Код:
INSERT INTO dbo.[Группы пользователей] ([Наименование группы], [ФИО_админа])
		VALUES ('Группа 1', 'Иванов')
Снова все отлично вставилось.
Теперь доходят руки до применения триггера. Пишу код:
Код:
UPDATE dbo.[Сотрудники]
		SET 
			[ФИО]='Иванов Иван Иванович',
			[Уровень доступа]='94'
		WHERE 
				[ФИО]='Иванов'
Но в ответ ошибка: "Сообщение 547, уровень 16, состояние 0, строка 1
Конфликт инструкции UPDATE с ограничением REFERENCE "Relationship21". Конфликт произошел в базе данных "12", таблица "dbo.Группы пользователей", column 'ФИО_админа'.
Выполнение данной инструкции было прервано.". Такое чувство, что не срабатывает триггер. Ладно, запускаю в режиме отладки предоставленный код(F11) и наблюдаю, что инструкция прерывается уже на первой строчке(на строке "UPDATE dbo.[Сотрудники]"), т.е. даже до SET не доходит!!!
Подскажите пожалуйста, что не так в моей базе, каким образом нужно изменить предоставленный триггер, чтобы он делал то, что я от него ожидал(при изменении таблицы "Сотрудники" изменял соответствующим образом таблицу "Группы пользователей")? Еще раз повторю, что разбираюсь с реализацией триггеров и прекрасно понимаю, что в данном случае можно просто изменить тип связи на Cascade и все заработает без них.
Кроме желания научиться писать триггеры, создать данную тему меня побудили чисто практические интересы. Посмотрите на выделенную в коде определения БД строку, обратите внимание откуда берется поле [ФИО_админа]. Если заметили, то получается "прямая циклическая связь" между таблицами(таблица "Сотрудники" связана с таблицей "Группы пользователей", а "Группы пользователей" с таблицей "Сотрудники").
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.
Mixim вне форума Ответить с цитированием
Старый 03.05.2012, 15:45   #2
=master=
Форумчанин
 
Регистрация: 26.03.2012
Сообщений: 665
По умолчанию

Доходит до SET. Оттого и ошибка.
=master= вне форума Ответить с цитированием
Старый 03.05.2012, 16:11   #3
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
По умолчанию

Цитата:
Сообщение от =master= Посмотреть сообщение
Доходит до SET. Оттого и ошибка.
Чего-чего, можно по-подробнее и по-яснее?
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.
Mixim вне форума Ответить с цитированием
Старый 04.05.2012, 07:10   #4
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
Сообщение

Исправил свои ошибки:
1)неправильный тип связи был установлен между таблицами;
2)триггер надо было писать по другому.

Если кому-то будет интересно, то вот SQL-запрос для создания корректной БД с требуемыми параметрами:
Код:
/*
Created: 03.05.2012
Modified: 04.05.2012
Model: Microsoft SQL Server 2008
Database: MS SQL Server 2008
*/

-- Create tables section -------------------------------------------------

-- Table Сотрудники

CREATE TABLE [Сотрудники]
(
 [ФИО] Varchar(100) NOT NULL,
 [Уровень доступа] Int NULL,
 [Наименование группы] Varchar(100) NULL,
 [ФИО админа] Varchar(100) NULL
)
go

-- Add keys for table Сотрудники

ALTER TABLE [Сотрудники] ADD CONSTRAINT [Key1] PRIMARY KEY ([ФИО])
go

-- Create triggers for table Сотрудники

CREATE TRIGGER [Update_Trigger]
 
   ON  Сотрудники 
   /*AFTER DELETE*/
   /*for delete*/
   /*BEFORE DELETE*/
   /*for delete*/
   instead of delete
AS 
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

declare
	@фио_select1 varchar(100),	
	@фио_select2 varchar(100);

select @фио_select2=[ФИО] from deleted
	
DECLARE myCursor cursor for
	SELECT [ФИО админа]
	FROM [Администраторы]
	WHERE [ФИО админа]=@фио_select2
	
OPEN myCursor
	FETCH NEXT FROM myCursor INTO @фио_select1


	



if(@фио_select1=@фио_select2)
	begin
		raiserror('На данного сотрудника есть ссылки, удалять его нельзя', 16, 1)
	end
else
	begin
		  delete [Сотрудники] where [Сотрудники].[ФИО]=@фио_select2
	end


END
go

-- Table Группы пользователей

CREATE TABLE [Группы пользователей]
(
 [Наименование группы] Varchar(100) NOT NULL,
 [ФИО админа] Varchar(100) NOT NULL
)
go

-- Add keys for table Группы пользователей

ALTER TABLE [Группы пользователей] ADD CONSTRAINT [Key2] PRIMARY KEY ([Наименование группы],[ФИО админа])
go

-- Table Администраторы

CREATE TABLE [Администраторы]
(
 [ФИО админа] Varchar(100) NOT NULL
)
go

-- Add keys for table Администраторы

ALTER TABLE [Администраторы] ADD CONSTRAINT [Key3] PRIMARY KEY ([ФИО админа])
go

-- Create relationships section ------------------------------------------------- 

ALTER TABLE [Администраторы] ADD CONSTRAINT [Relationship1] FOREIGN KEY ([ФИО админа]) REFERENCES [Сотрудники] ([ФИО]) ON UPDATE CASCADE ON DELETE CASCADE
go

ALTER TABLE [Группы пользователей] ADD CONSTRAINT [Relationship2] FOREIGN KEY ([ФИО админа]) REFERENCES [Администраторы] ([ФИО админа]) ON UPDATE CASCADE ON DELETE CASCADE
go

ALTER TABLE [Сотрудники] ADD CONSTRAINT [Relationship3] FOREIGN KEY ([Наименование группы], [ФИО админа]) REFERENCES [Группы пользователей] ([Наименование группы], [ФИО админа]) ON UPDATE NO ACTION ON DELETE NO ACTION
go
Как видно, была создана дополнительная таблица "Администраторы". Убежден, что от неё можно смело отказаться. Сам этого пока не сделал, т.к. это тестовый пример, ради создания которого я погубил около десятка миллионов нервных клеток.
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.
Mixim вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
реализация в QT navolo4ka Qt и кроссплатформенное программирование С/С++ 0 10.02.2012 15:39
Лабораторная работа. Реализация алгоритмов выбора и поиска BilliBong Помощь студентам 2 21.12.2011 01:59
Лабораторная работа. Реализация одного из методов оптимизации MadLow Фриланс 3 11.12.2011 19:04
Реализация двух потоков, работа с буфером, механизм семафоров (С++ или Delphi) shoonya Помощь студентам 0 05.04.2010 14:08
Работа с триггерами Vinas БД в Delphi 2 04.12.2007 23:45