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

Откуда:
Сообщений: 142
Здравствуйте!
Вот такая интересная петрушка у меня получается: в триггере определено несколько бизнес-правил, некоторые из них не срабатывают при инсерте строки, а только при апдейте, но если их разместить в отдельном триггере, потом все работает.
Где грабли зарылись? Может лучше действительно создавать отдельный триггер для каждого правила?
20 дек 13, 15:02    [15323690]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
Glory
Member

Откуда:
Сообщений: 104751
andrej2005
Где грабли зарылись?

В написанном вами коде

andrej2005
Может лучше действительно создавать отдельный триггер для каждого правила?

Слишком общий вопрос.
20 дек 13, 15:04    [15323703]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
USE [Projekce]
GO
/****** Object:  Trigger [4_blok].[trigUPDATE_PROPOJ]    Script Date: 12/19/2013 10:03:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [4_blok].[trigUPDATE_PROPOJ]
ON [4_blok].[PROPOJ_4B]
FOR INSERT, DELETE, UPDATE
AS

BEGIN		
	IF (NOT EXISTS(SELECT * FROM deleted)) AND (NOT EXISTS(SELECT * FROM inserted))
        RETURN

    IF NOT EXISTS(SELECT * FROM deleted)
    BEGIN 
		BEGIN
			UPDATE [4_blok].[PROPOJ_4B]
			SET [4_blok].[PROPOJ_4B].Projektant = ORIGINAL_LOGIN(), 
				[4_blok].[PROPOJ_4B].DatumČas = GETDATE()
			FROM [4_blok].[PROPOJ_4B] 
				INNER JOIN inserted 
				ON [4_blok].[PROPOJ_4B].ID_PROPOJ=inserted.ID_PROPOJ;
		END;
		INSERT INTO [Propoj_UPDATE_B44]	
			([PROJEKTANT]
			,[DATUMČAS]	
			,[OPERACE]
			,[ID_PROPOJ]
			,[ID]
			,[POTENCIAL]
			,[OZN_ZAR_A]
			,[PRISTROJ_A]
			,[SVORKA_A]
			,[STRANA_A]
			,[KOD_KABELU]
			,[OZN_ZAR_Z]
			,[PRISTROJ_Z]
			,[SVORKA_Z]
			,[STRANA_Z]
			,[POZNAMKA]
			,[TRANZIT])
		SELECT 
			ORIGINAL_LOGIN()
			,GETDATE()
			,'insert'
			,[ID_PROPOJ]
			,[ID]
			,[POTENCIAL]
			,[OZN_ZAR_A]
			,[PRISTROJ_A]
			,[SVORKA_A]
			,[STRANA_A]
			,[KOD_KABELU]
			,[OZN_ZAR_Z]
			,[PRISTROJ_Z]
			,[SVORKA_Z]
			,[STRANA_Z]
			,[POZNAMKA]
			,[TRANZIT]
		FROM inserted			
		RETURN
    END;

    IF NOT EXISTS(SELECT * FROM inserted)
    BEGIN
		INSERT INTO [Propoj_UPDATE_B44]	
			([PROJEKTANT]
			,[DATUMČAS]	
			,[OPERACE]
			,[ID_PROPOJ]
			,[ID]
			,[POTENCIAL]
			,[OZN_ZAR_A]
			,[PRISTROJ_A]
			,[SVORKA_A]
			,[STRANA_A]
			,[KOD_KABELU]
			,[OZN_ZAR_Z]
			,[PRISTROJ_Z]
			,[SVORKA_Z]
			,[STRANA_Z]
			,[POZNAMKA]
			,[TRANZIT])
		SELECT 
			ORIGINAL_LOGIN()
			,GETDATE()
			,'delete'
			,[ID_PROPOJ]
			,[ID]
			,[POTENCIAL]
			,[OZN_ZAR_A]
			,[PRISTROJ_A]
			,[SVORKA_A]
			,[STRANA_A]
			,[KOD_KABELU]
			,[OZN_ZAR_Z]
			,[PRISTROJ_Z]
			,[SVORKA_Z]
			,[STRANA_Z]
			,[POZNAMKA]
			,[TRANZIT]
		FROM deleted
		RETURN
    END;
	 
	BEGIN
		UPDATE [4_blok].[PROPOJ_4B]
		SET [4_blok].[PROPOJ_4B].Projektant = ORIGINAL_LOGIN(), 
			[4_blok].[PROPOJ_4B].DatumČas = GETDATE()
		FROM [4_blok].[PROPOJ_4B] 
			INNER JOIN inserted 
			ON [4_blok].[PROPOJ_4B].ID_PROPOJ=inserted.ID_PROPOJ;
	END;	
	INSERT INTO [Propoj_UPDATE_B44]		
		([OPERACE]
		,[DATUMČAS]	
		,[PROJEKTANT]
		,[ID_PROPOJ]
		,[ID]
		,[POTENCIAL]
		,[OZN_ZAR_A]
		,[PRISTROJ_A]
		,[SVORKA_A]
		,[STRANA_A]
		,[KOD_KABELU]
		,[OZN_ZAR_Z]
		,[PRISTROJ_Z]
		,[SVORKA_Z]
		,[STRANA_Z]
		,[POZNAMKA]
		,[TRANZIT])
	SELECT
		'update'
		,B.[DatumČas]
		,B.[PROJEKTANT]
		,A.[ID_PROPOJ]
		,A.[ID]
		,A.[POTENCIAL]
		,A.[OZN_ZAR_A]
		,A.[PRISTROJ_A]
		,A.[SVORKA_A]		
		,A.[STRANA_A]
		,A.[KOD_KABELU]
		,A.[OZN_ZAR_Z]
		,A.[PRISTROJ_Z]
		,A.[SVORKA_Z]
		,A.[STRANA_Z]
		,A.[POZNAMKA]
		,A.[TRANZIT]
	FROM inserted AS A
			INNER JOIN [4_blok].[PROPOJ_4B] AS B 
			ON B.ID_PROPOJ=A.ID_PROPOJ;

	--zrcadlova kontrola propoju
	IF EXISTS	(SELECT	x.[OZN_ZAR_A], 
						x.[PRISTROJ_A],
						x.[SVORKA_A],
						x.[OZN_ZAR_Z], 
						x.[PRISTROJ_Z],
						x.[SVORKA_Z]	
				FROM [4_blok].[PROPOJ_4B] AS y
				INNER JOIN inserted AS x ON		x.[OZN_ZAR_A] = y.[OZN_ZAR_Z]
											AND x.[PRISTROJ_A] = y.[PRISTROJ_Z]
											AND x.[SVORKA_A] = y.[SVORKA_Z]
											AND x.[OZN_ZAR_Z] = y.[OZN_ZAR_A]
											AND x.[PRISTROJ_Z] = y.[PRISTROJ_A]
											AND x.[SVORKA_Z] = y.[SVORKA_A]
				)
	BEGIN
		RAISERROR ('Chyba! Propojení již existuje!', 16, 1)
		ROLLBACK TRANSACTION
	END;

	--kontrola propojeni sv-ky strana A
	--sv-ka muze byt zapojena pouze dva krat!
	DECLARE @CountOf bigint,
			@CountOf_STRANA_A bigint,
			@CountOf_STRANA_Z bigint,
			@OZN_ZAR_A nvarchar(255),
			@PRISTROJ_A nvarchar(255),
			@SVORKA_A nvarchar(255),
			@STRANA_A nvarchar(255),	
			@OZN_ZAR_Z nvarchar(255),
			@PRISTROJ_Z nvarchar(255),
			@SVORKA_Z nvarchar(255),
			@STRANA_Z nvarchar(255);
		WITH sp AS	(
			SELECT	OZN_ZAR_A,
					PRISTROJ_A, 
					SVORKA_A, 
					STRANA_A, 
					OZN_ZAR_Z, 
					PRISTROJ_Z, 
					SVORKA_Z,
					STRANA_Z 
			FROM		[4_blok].[PROPOJ_4B]
			UNION ALL
			SELECT	OZN_ZAR_Z AS OZN_ZAR_A, 
					PRISTROJ_Z AS PRISTROJ_A, 
					SVORKA_Z AS SVORKA_A, 
					STRANA_Z AS STRANA_A, 
					OZN_ZAR_A AS OZN_ZAR_Z, 
					PRISTROJ_A AS PRISTROJ_Z, 
					SVORKA_A AS SVORKA_Z,
					STRANA_A AS STRANA_Z
			FROM	[4_blok].[PROPOJ_4B]
		)
		SELECT	@OZN_ZAR_A=sp.OZN_ZAR_A, 
				@PRISTROJ_A=sp.PRISTROJ_A, 
				@SVORKA_A=sp.SVORKA_A, 
				@STRANA_A=sp.STRANA_A,
				@OZN_ZAR_Z=sp.OZN_ZAR_Z, 
				@PRISTROJ_Z=sp.PRISTROJ_Z, 
				@SVORKA_Z=sp.SVORKA_Z,
				@STRANA_Z=sp.STRANA_Z,
				@CountOf=COUNT(sp.OZN_ZAR_A) OVER(PARTITION BY sp.OZN_ZAR_A, sp.PRISTROJ_A, sp.SVORKA_A), 
				@CountOf_STRANA_A=COUNT(sp.STRANA_A) OVER(PARTITION BY sp.STRANA_A)
		FROM sp
		INNER JOIN inserted AS so ON  
			sp.OZN_ZAR_A = so.OZN_ZAR_A AND
			sp.PRISTROJ_A = so.PRISTROJ_A AND
			sp.SVORKA_A = so.SVORKA_A;	

	IF @CountOf>=2
	BEGIN
		RAISERROR ('Chyba! SVORKA_A je kompletně zapojená!', 16, 1)
		ROLLBACK TRANSACTION
	END;

	IF @CountOf_STRANA_A>1 AND @STRANA_A='DL'
	BEGIN
		RAISERROR ('Chyba! SVORKA_A již je DL zapojená!', 16, 1)
		ROLLBACK TRANSACTION
	END;

	IF @CountOf_STRANA_A>1 AND @STRANA_A='HP'
	BEGIN
		RAISERROR ('Chyba! SVORKA_A již je HP zapojená!', 16, 1)
		ROLLBACK TRANSACTION
	END;

	--kontrola propojeni sv-ky strana Z
	--sv-ka muze byt zapojena pouze dva krat!
		WITH sp1 AS	(
			SELECT	OZN_ZAR_A,
					PRISTROJ_A, 
					SVORKA_A, 
					STRANA_A, 
					OZN_ZAR_Z, 
					PRISTROJ_Z, 
					SVORKA_Z,
					STRANA_Z 
			FROM		[4_blok].[PROPOJ_4B]
			UNION ALL
			SELECT	OZN_ZAR_Z AS OZN_ZAR_A, 
					PRISTROJ_Z AS PRISTROJ_A, 
					SVORKA_Z AS SVORKA_A, 
					STRANA_Z AS STRANA_A, 
					OZN_ZAR_A AS OZN_ZAR_Z, 
					PRISTROJ_A AS PRISTROJ_Z, 
					SVORKA_A AS SVORKA_Z,
					STRANA_A AS STRANA_Z
			FROM	[4_blok].[PROPOJ_4B]
		)
		SELECT	@OZN_ZAR_A=sp1.OZN_ZAR_A, 
				@PRISTROJ_A=sp1.PRISTROJ_A, 
				@SVORKA_A=sp1.SVORKA_A, 
				@STRANA_A=sp1.STRANA_A,  
				@OZN_ZAR_Z=sp1.OZN_ZAR_Z, 
				@PRISTROJ_Z=sp1.PRISTROJ_Z, 
				@SVORKA_Z=sp1.SVORKA_Z,
				@STRANA_Z=sp1.STRANA_Z, 
				@CountOf=COUNT(sp1.OZN_ZAR_A) OVER(PARTITION BY sp1.OZN_ZAR_A, sp1.PRISTROJ_A, sp1.SVORKA_A), 
				@CountOf_STRANA_Z=COUNT(sp1.STRANA_A) OVER(PARTITION BY sp1.STRANA_A)
		FROM sp1
		INNER JOIN inserted AS so1 ON 
			sp1.OZN_ZAR_A = so1.OZN_ZAR_Z AND
			sp1.PRISTROJ_A = so1.PRISTROJ_Z AND
			sp1.SVORKA_A = so1.SVORKA_Z;	

	IF @CountOf>=2
	BEGIN
		RAISERROR ('Chyba! SVORKA_Z je kompletně zapojená!', 16, 1)
		ROLLBACK TRANSACTION
	END;

	IF @CountOf_STRANA_Z>1 AND @STRANA_A='DL'
	BEGIN
		RAISERROR ('Chyba! SVORKA_Z již je DL zapojená!', 16, 1)
		ROLLBACK TRANSACTION
	END;

	IF @CountOf_STRANA_Z>1 AND @STRANA_A='HP'
	BEGIN
		RAISERROR ('Chyba! SVORKA_Z již je HP zapojená!', 16, 1)
		ROLLBACK TRANSACTION
	END;
END;	
20 дек 13, 15:28    [15323873]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
Glory
Member

Откуда:
Сообщений: 104751
Ошибка в 17ой строке. Как всегда
20 дек 13, 15:30    [15323889]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
--zrcadlova kontrola propoju

в этом месте уже не работает
20 дек 13, 15:30    [15323890]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
    BEGIN 
		BEGIN

всмысле, здесь?
20 дек 13, 15:32    [15323902]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
StarikNavy
Member

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

вам намекнули что надо привести свои тестовые данные, скрипты таблиц, желаемый результат
20 дек 13, 15:58    [15324089]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
Мистер Хенки
Member

Откуда: канализация
Сообщений: 6615
andrej2005,
это ж шутка про 17 строку )))
 IF NOT EXISTS(SELECT * FROM deleted)
    BEGIN 
		BEGIN
			UPDATE [4_blok].[PROPOJ_4B]
			SET [4_blok].[PROPOJ_4B].Projektant = ORIGINAL_LOGIN(), 
				[4_blok].[PROPOJ_4B].DatumČas = GETDATE()
			FROM [4_blok].[PROPOJ_4B] 
				INNER JOIN inserted 
				ON [4_blok].[PROPOJ_4B].ID_PROPOJ=inserted.ID_PROPOJ;
		END;
		INSERT INTO [Propoj_UPDATE_B44]	
			([PROJEKTANT]
			,[DATUMČAS]	
			,[OPERACE]
			,[ID_PROPOJ]
			,[ID]
			,[POTENCIAL]
			,[OZN_ZAR_A]
			,[PRISTROJ_A]
			,[SVORKA_A]
			,[STRANA_A]
			,[KOD_KABELU]
			,[OZN_ZAR_Z]
			,[PRISTROJ_Z]
			,[SVORKA_Z]
			,[STRANA_Z]
			,[POZNAMKA]
			,[TRANZIT])
		SELECT 
			ORIGINAL_LOGIN()
			,GETDATE()
			,'insert'
			,[ID_PROPOJ]
			,[ID]
			,[POTENCIAL]
			,[OZN_ZAR_A]
			,[PRISTROJ_A]
			,[SVORKA_A]
			,[STRANA_A]
			,[KOD_KABELU]
			,[OZN_ZAR_Z]
			,[PRISTROJ_Z]
			,[SVORKA_Z]
			,[STRANA_Z]
			,[POZNAMKA]
			,[TRANZIT]
		FROM inserted			
		RETURN
    END;

мне кажется, что при вставке на этом if триггер и заканчивается, потому что вы делаете return
20 дек 13, 16:05    [15324115]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
Ну и шуточки у вас, господа! У человека задница в мыле, а вы с шуточками.
Пока не представляю, как вам подать тестовые данные, неужели никто не видит в предложенном коде ошибку?

Мистер Хенки - нет, в этом месте заносится в журнал изменений информация о апдейтах, и это работает.
20 дек 13, 17:21    [15324645]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
Мистер Хенки
Member

Откуда: канализация
Сообщений: 6615
andrej2005
Ну и шуточки у вас, господа! У человека задница в мыле, а вы с шуточками.
Пока не представляю, как вам подать тестовые данные, неужели никто не видит в предложенном коде ошибку?

Мистер Хенки - нет, в этом месте заносится в журнал изменений информация о апдейтах, и это работает.

естественно работает. RETURN срабатывает и триггер заканчивается.
20 дек 13, 17:23    [15324659]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Как сервер должен понять вот это?
[4_blok].[PROPOJ_4B].DatumČas = GETDATE()
20 дек 13, 17:30    [15324705]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
iap
Member

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

напишите алиасы ко всем таблицам, представлениям и функциям запроса
и напишите эти алиасы для всех полей запроса.
Писатьь [4_blok].[PROPOJ_4B].Datum - не дело.
20 дек 13, 17:32    [15324720]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
Почему тогда триггер работает после вставки строки при апдейте?
20 дек 13, 17:34    [15324729]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
iap
Как сервер должен понять вот это?
[4_blok].[PROPOJ_4B].DatumČas = GETDATE()

некорректно отобразился чешский коллейшн
20 дек 13, 17:38    [15324771]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
Мистер Хенки
Member

Откуда: канализация
Сообщений: 6615
andrej2005
Почему тогда триггер работает после вставки строки при апдейте?

потому что вы его так написали )))
При апдейте до вставки строки с 'update' он доходит
20 дек 13, 17:39    [15324783]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
подправил немного, здесь добавляю время изменения

[4_blok].[PROPOJ_4B].Datum4as = GETDATE()
20 дек 13, 17:45    [15324847]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
andrej2005
Member

Откуда:
Сообщений: 142
Мистер Хенки
andrej2005
Ну и шуточки у вас, господа! У человека задница в мыле, а вы с шуточками.
Пока не представляю, как вам подать тестовые данные, неужели никто не видит в предложенном коде ошибку?

Мистер Хенки - нет, в этом месте заносится в журнал изменений информация о апдейтах, и это работает.

естественно работает. RETURN срабатывает и триггер заканчивается.


Да, правильно, грабли в этом RETURN. Спасибо! Но проблемма - RETURN там нужен для правильного занесения изменений в журнал при инсерте, апдейте и делите. Думаю как не наступать на эти грабли... Самое простое решение уже есть, это создать второй треггер. Но я попробую исправить исходный код.
Спасибо!
20 дек 13, 17:54    [15324885]     Ответить | Цитировать Сообщить модератору
 Re: Триггер и бизнес-правила  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31994
andrej2005
Может лучше действительно создавать отдельный триггер для каждого правила?
Лучше делать один триггер для всех бизнес-правил - будет проще этим управлять.

Однако для UPDATE INSERT DELETE я бы делал отдельные триггеры - будет проще их писать (хотя иногда код придётся и копировать).
andrej2005
Но проблемма - RETURN там нужен для правильного занесения изменений в журнал при инсерте, апдейте и делите.
RETURN для этого не нужен - ведь вы проверяете наличие строк в псевдотаблицах inserted, deleted. Хотя, повторю, я бы сделал отдельные триггеры.
20 дек 13, 18:25    [15325020]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить