문제

나는지 알고 싶은 경우가 어쨌든 난 추가 할 수 있습 트리거에는 두 테이블에 복제 데이터습니다.

예를 들어:

  • 나는 두 명의 사용자,테이블,users_V1 및 users_V2,사용자가입 업데이트로의 하나 V1 응용 프로그램,그것을 트리거를 활성화에를 업데이트 users_V2 니다.

  • 를 추가하고 싶은 경우에는 동일에서 트리거 V2 기 위해 테이블에 데이터를 업데이트 V1 할 때 사용자에서 업데이트 V2,갈 것으로는 무한 루프가?방법은 없을 피할 것.

도움이 되었습니까?

해결책

처리 중에 트리거를 명시 적으로 비활성화하는 것이 좋습니다. 이로 인해 이상한 부작용이 발생할 수 있습니다.

트리거에서 사이클을 감지 (및 예방)하는 가장 신뢰할 수있는 방법은 사용하는 것입니다. CONTEXT_INFO().

예시:

CREATE TRIGGER tr_Table1_Update
ON Table1
FOR UPDATE AS

DECLARE @ctx VARBINARY(128) 
SELECT @ctx = CONTEXT_INFO() 
IF @ctx = 0xFF
    RETURN

SET @ctx = 0xFF

-- Trigger logic goes here

보다 이 링크 더 자세한 예를 위해.


참고 CONTEXT_INFO() SQL Server 2000에서 :

컨텍스트 정보는 지원되지만 분명히 CONTEXT_INFO 기능은 아닙니다. 대신 이것을 사용해야합니다.

SELECT @ctx = context_info
FROM master.dbo.sysprocesses
WHERE spid = @@SPID

다른 팁

  • 어느 쪽이든 trigger_nestlevel () 트리거 재귀를 제한하기 위해, 또는

  • 업데이트가 전혀 필요한지 대상 테이블을 확인하십시오.

    IF (SELECT COUNT(1) 
    FROM users_V1 
    INNER JOIN inserted ON users_V1.ID = inserted.ID
    WHERE users_V1.field1 <> inserted.field1
    OR users_V1.field2 <> inserted.field2) > 0 BEGIN
    
    UPDATE users_V1 SET ...
    

나는 똑같은 문제가 있었다. Context_Info ()를 사용하려고 시도했지만 세션 변수이므로 처음으로 만 작동합니다! 다음에 세션 중에 방아쇠가 발생하면 작동하지 않습니다. 그래서 나는 영향을받는 각 트리거에서 출구로 둥지 레벨을 반환하는 변수를 사용하게되었습니다.

예시:

CREATE TRIGGER tr_Table1_Update
ON Table1
FOR UPDATE AS
BEGIN
      --Prevents Second Nested Call
      IF @@NESTLEVEL>1 RETURN 

      --Trigger logic goes here
END

참고 : 또는 @@ Nestlevel> 0을 사용하여 모든 중첩 된 통화를 중지하려는 경우

또 다른 메모 -이 기사에는 중첩 된 전화 및 재귀 통화에 대한 혼란이 많은 것 같습니다. 원래 포스터는 하나의 방아쇠가 다른 방아쇠를 발사 할 수있는 중첩 방아쇠를 참조하여 첫 번째 트리거가 다시 발사 될 수 있습니다. 이것은 중첩되었지만 SQL Server에 따르면 트리거가 직접 호출/트리거되지 않기 때문에 재귀는 아닙니다. 재귀는 "한 번의 트리거가 다른 트리거를 부르는 곳"이 아닙니다. 그것은 중첩되었지만 반드시 재귀는 아닙니다. 여기에 언급 된 일부 설정으로 재귀를 활성화/비활성화하고 둥지로하여이를 테스트 할 수 있습니다. 중첩에 대한 블로그 게시물

나는 아무거 캠프 이를 위해 특별한 디자인이 시나리오이다.을 말하고는,제한된 기술이 나는 것에 대해지고 왜 그것은,여기에 내 전체적인 분석:

를 사용하여 트리거에는 테이블용할 수 있는 행동에 대해 모든 작업 테이블에 있습니다.는 그것은,당신의 주요 혜택을 경우에.하지만 그는 것을 의미가 있는 사용자와 직접 액세스하거나 테이블에 여러 액세스 포인트이 있습니다.내가 피하려는 경향이 있다.트리거들(나는 그들을 사용이 많이),그러나 그것은 하나의 마지막 데이터베이스 디자인 툴 내가 사용하는 경향이 있기 때문에 많이 알고하지 않에 대해 자신의 컨텍스트(일반적으로,강도)및 사용할 때 장소에 그들에 대해 알 필요가 서로 다른 상황과 전반적인 사용 경우,자신의 혜택은 약해진다.

는 경우에는 모두 응용 프로그램 버전이 필요해 트리거 동일한 작업,그들은 모두 전화 저장 proc.저장 proc 할 수 있도록 모든 적절한 작업을 수행하며,때 앱이 더 이상 필요를 지원하는 V1,다음의 일부를 저장 proc 제거할 수 있습니다.

부르 두 저장되던 클라이언트 코드에서는 나쁜 생각하기 때문에,이것은 추상화 계층의 데이터 서비스는 데이터베이스를 제공할 수 있습 쉽고,지속적으로이 응용 프로그램을 걱정했습니다.

내가 선호하는 제어 인터페이스의 기본 테이블-중 하나와 함께망 또는 Udf 또는 SPs.사용자는 결코 얻을 직접 액세스 테이블에 있습니다.또 다른 점은 여기에서 기다리고 있습니다 현재 하나의"사용자"를 보기 또는 UDF 를 결합에 적절한 기본 테이블의 없이 사용자에 대해 아는 것도 아마을이 있지 않더라도"어떤 동기화"필요하기 때문에 새로운 특성에 EAV 시스템을 필요로 하는 경우 종류의 병리학적인 유연성이나 다른 다른 구조를 할 수 있는 여전히 합치-말 외부 적용 UDF 등입니다.

트리거 내에 일종의 루프백 감지를 만들어야합니다. 아마도 다음 테이블에 입력하기 전에 레코드가 존재하는지 확인하기 위해 "존재하는 경우"명령문을 사용합니다. 그것은 현재 설정된 방식으로 무한 루프로 들어가는 것처럼 들립니다.

전염병과 같은 트리거를 피하십시오 .... 저장된 절차를 사용하여 사용자를 추가하십시오. 이것이 약간의 디자인 변경이 필요한 경우이를 만들어냅니다. 트리거는 악입니다.

같은 것을 시도하십시오 (나는 당신이 이미 그 부분을 작성하는 방법을 분명히 알고있는 것처럼 트리거 트리거를 귀찮게하지 않았습니다) :

update t
set field1 = i.field1
field2 = i.field2
from inserted i
join table1 t on i.id  = t.id
where field1 <> i.field1 OR field2 <> i.field2

트리거의 재귀, 즉 하나의 트리거를 다른 사람에게 호출하는 것은 다음으로 제한됩니다. 32 레벨

각 트리거에서 삽입하려는 행이 이미 존재하는지 확인하십시오.

예시

CREATE TRIGGER Table1_Synchronize_Update ON [Table1] FOR UPDATE AS
BEGIN
  UPDATE  Table2
  SET     LastName = i.LastName
          , FirstName = i.FirstName
          ,  ... -- Every relevant field that needs to stay in sync
  FROM    Table2 t2
          INNER JOIN Inserted i ON i.UserID = t2.UserID
  WHERE   i.LastName <> t2.LastName
          OR i.FirstName <> t2.FirstName
          OR ... -- Every relevant field that needs to stay in sync
END

CREATE TRIGGER Table1_Synchronize_Insert ON [Table1] FOR INSERT AS
BEGIN
  INSERT INTO Table2
  SELECT i.*
  FROM   Inserted i
         LEFT OUTER JOIN Table2 t2 ON t2.UserID = i.UserID
  WHERE  t2.UserID IS NULL
END

CREATE TRIGGER Table2_Synchronize_Update ON [Table2] FOR UPDATE AS
BEGIN
  UPDATE  Table1
  SET     LastName = i.LastName
          , FirstName = i.FirstName
          ,  ... -- Every relevant field that needs to stay in sync
  FROM    Table1 t1
          INNER JOIN Inserted i ON i.UserID = t1.UserID
  WHERE   i.LastName <> t1.LastName
          OR i.FirstName <> t1.FirstName
          OR ... -- Every relevant field that needs to stay in sync
END

CREATE TRIGGER Table2_Synchronize_Insert ON [Table2] FOR INSERT AS
BEGIN
  INSERT INTO Table1
  SELECT i.*
  FROM   Inserted i
         LEFT OUTER JOIN Table1 t1 ON t1.UserID = i.UserID
  WHERE  t1.UserID IS NULL
END
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top