특정 실행 범위에 대해 SQL 서버 트리거를 비활성화하는 방법이 있습니까?

StackOverflow https://stackoverflow.com/questions/174600

  •  05-07-2019
  •  | 
  •  

문제

SQL Server 2005에서 트리거가 트리거를 발사 할 책임이있는 개체를 찾을 수있는 방법이 있습니까? 저장된 전신의 트리거를 비활성화하는 데 이것을 사용하고 싶습니다.

현재 트랜잭션에 대해서만 트리거를 비활성화하는 다른 방법이 있습니까? 다음 코드를 사용할 수는 있지만 실수하지 않으면 동시 거래에도 영향을 미칩니다. 이는 나쁜 일입니다.

DISABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

가능하다면 테이블에 "Notrigger"필드를 갖는 기술을 피하고 NoTrigger = null, 가능한 한 작은 테이블을 유지하고 싶기 때문입니다.

방아쇠를 피하고 싶은 이유는 테이블에 대한 수동 업데이트에 중요한 논리가 포함되어 있기 때문에 저장된 절차 가이 논리를 처리하기 때문입니다. 이것은 고도로 사용되는 절차가 될 것이기 때문에, 나는 그것이 빠르기를 원합니다.

트리거는 암시 적 트랜잭션을 시작하기 때문에 서버에 추가 오버 헤드를 부과합니다. 트리거가 실행 되 자마자 새로운 암시 적 트랜잭션이 시작되며 트랜잭션 내의 데이터 검색은 영향을받는 테이블에 잠금을 보유합니다.

에서: http://searchsqlserver.techtarget.com/tip/1,289483,SID87_GCI1170220,00.html#trigger

도움이 되었습니까?

해결책

방금이 기사가 최근 SQL Server Central 뉴스 레터에서 강조된 것을 보았으며 연결에서 Context_Info를 사용하는 유용한 방법을 제공하는 것으로 보입니다.

http://www.mssqltips.com/tip.asp?tip=1591


Terrapin의 편집 :

위의 링크에는 다음 코드가 포함됩니다.

USE AdventureWorks;  
GO  
-- creating the table in AdventureWorks database  
IF OBJECT_ID('dbo.Table1') IS NOT NULL  
DROP TABLE dbo.Table1  
GO  
CREATE TABLE dbo.Table1(ID INT)  
GO   
-- Creating a trigger  
CREATE TRIGGER TR_Test ON dbo.Table1 FOR INSERT,UPDATE,DELETE  
AS  
DECLARE @Cinfo VARBINARY(128)  
SELECT @Cinfo = Context_Info()  
IF @Cinfo = 0x55555  
RETURN  
PRINT 'Trigger Executed'  
-- Actual code goes here  
-- For simplicity, I did not include any code  
GO  

트리거가 실행되는 것을 방지하려면 다음을 수행 할 수 있습니다.

SET Context_Info 0x55555 
INSERT dbo.Table1 VALUES(100)

다른 팁

트리거가 응용 프로그램에서 성능 문제를 일으키는 경우 가장 좋은 방법은 테이블의 모든 수동 업데이트를 제거하고 올바른 업데이트 로직이 포함 된 삽입/업데이트 저장 프로 시저를 통해 모든 업데이트가 필요합니다. 그런 다음 트리거를 완전히 제거 할 수 있습니다.

다른 것이 작동하지 않으면 테이블 업데이트 권한을 거부하는 것이 좋습니다.

이것은 또한 중복 코드의 문제를 해결합니다. 업데이트 SP와 트리거의 코드 복제는 좋은 소프트웨어 엔지니어링 원칙을 위반하는 것이며 유지 보수 문제가 될 것입니다.

ALTER TABLE TBL 트리거 TRG를 비활성화합니다

http://doc.ddart.net/mssql/sql70/aa-az_5.htm

그래도 첫 번째 단락의 의미를 이해하지 못합니다.

트리거에 모든 업데이트, 심지어 수동 업데이트를 처리하기위한 논리가 포함되어 있기 때문에 로직이있는 위치이어야합니다. 저장된 절차가 "이 논리를 처리하는"절차는 중복 코드를 의미하는 언급 된 예제입니다. 또한 모든 업데이트 문에 저자에 관계 없이이 논리가 적용되는지 확인하려면 트리거가 그 장소입니다. 누군가가 절차를 저술하지만 논리를 다시 복제하는 것을 잊어 버릴 때 어떻게됩니까? 논리를 수정할 때가되면 어떻게됩니까?

이것이 좋은 생각인지 확실하지 않지만 그것은 나에게 효과가있는 것 같습니다. 트리거가 비활성화되는 동안 트랜잭션은 다른 프로세스에서 테이블에 삽입물을 방지해야합니다.

IF OBJECT_ID('dbo.TriggerTest') IS NOT NULL
 DROP PROCEDURE dbo.TriggerTest
GO

CREATE PROCEDURE [dbo].[TriggerTest]
AS
BEGIN TRANSACTION trnInsertTable1s
;
DISABLE TRIGGER trg_tblTable1_IU ON tblTable1
;
BEGIN -- Procedure Code
    PRINT '@@trancount'
    PRINT @@TRANCOUNT
    -- Do Stuff

END -- Procedure Code
;
ENABLE TRIGGER trg_tblTable1_IU ON tblTable1

IF @@ERROR <> 0 ROLLBACK TRANSACTION
ELSE COMMIT TRANSACTION

트리거를 비활성화하지 마십시오. 귀하는 동시 거래에 대해 비활성화하는 것이 맞습니다.

트리거를 비활성화하려는 이유는 무엇입니까? 그것은 무엇을합니까? 트리거가 문제를 일으키는 이유는 무엇입니까? 일반적으로 데이터 무결성 관점에서 Tigger를 비활성화하는 것은 나쁜 생각입니다.

성능이 문제가되는 경우 성능을 입력하기 위해 트리거를 다시 작성하는 것을 고려하십시오.

나는 이것에 대해 조금 waffed했다. 한편으로 나는 질문 게시물에 링크 된 기사에 명시된 이유와 더불어 내 테이블에 대해 실행되는 코드를 찾는 곳이 더 있기 때문에 주로 반 트리거가 주로 매우 반 트리거입니다.

반면에, 안정적이고 불변의 비즈니스 규칙 또는 교차 테이블 조치 (기록 테이블 유지 보수)를 시행하는 논리가 있다면이를 방아쇠로 가져 오는 것이 더 안전하므로 절차 저자와 프로그래머가 처리 할 필요가 없습니다. 그것으로 - 그것은 단지 작동합니다.

따라서, 내 권장 사항은이 Proc이 아닌 트리거에 필요한 논리를 동일한 면제로 여러 Procs로 자랄 것입니다.

방금 같은 문제에 직면하고 다음 해결책을 제시했습니다.

  1. 비활성화하려는 각 트리거에 대해 하나의 레코드가 포함 된 영구 DB 테이블을 만듭니다 (예 : reftriggerManager). 각 행에는 트리거 이름 (예 : strtriggername = 'mytrigger')과 비트 플래그 (예 : blndisabled, 기본값이 0)가 포함됩니다.

  2. 방아쇠의 시작 부분에서 reftriggerManager에서 strtriggerName = 'Mytrigger'를 찾으십시오. blndisabled = 1 인 경우 나머지 트리거 코드를 실행하지 않고 반환하면 트리거 코드를 완료하십시오.

  3. 트리거를 비활성화하려는 저장된 Proc에서 다음을 수행하십시오.


거래를 시작하십시오

reftriggermanager 업데이트 strtriggername = 'mytrigger'

/* 'Mytrigger'를 소유 한 테이블을 업데이트하지만 비활성화하려는 테이블. reftriggermanager.blndisabled = 1이므로 코드를 실행하지 않고 'Mytrigger'는 반환합니다. */

reftriggermanager 업데이트 set blndisabled = 0 where triggername = 'mytrigger'

/* 트리거를 발사하는 최종 업데이트 코드 선택. reftriggermanager.blndisabled = 0이므로 'Mytrigger'가 전체 실행됩니다. */

거래를 커밋합니다


이 모든 것은 거래 내에서 이루어 지므로 외부 세계에서 격리되어 대상 테이블의 다른 업데이트에 영향을 미치지 않습니다.

이 접근법에 문제가있는 사람이 있습니까?

계산서

나는 다른 답변과 동의합니다. 트리거를 비활성화하지 마십시오.

이것은 순수한 의견이지만 전염병과 같은 방아쇠를 피합니다. 데이터베이스 규칙을 시행하는 데 방아쇠가 사용 된 경우가 거의 발견되지 않았습니다. 내 경험에는 명백한 가장자리 사례가 있으며,이 진술을 할 경험 만 있습니다. 일반적으로 트리거가 일부 관계형 데이터 (비즈니스 로직에서 수행해야 함)를 삽입하거나 데이터를보고 테이블에 삽입하기 위해 (즉, 데이터를 비정상적으로 수행 할 수 있음) 데이터를 변환하는 데 사용되는 트리거를 보았습니다. 어떤 식 으로든.

트리거에는 합법적 인 용도가 있지만 일상적인 비즈니스 프로그래밍에서는 그 사이에 거의 없다고 생각합니다. 이것은 현재 문제에 도움이되지 않을 수 있지만 트리거를 완전히 제거하고 트리거가 다른 방식으로 수행하는 작업을 수행하는 것을 고려할 수 있습니다.

당신이 사용할 수있는 'exec'저장된 절차에서 디아블 및 유발 기능을 활성화합니다. 예시: EXEC ('ENABLE TRIGGER dbo.TriggerName on dbo.TriggeredTable')

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top