실제 변경 사항 만 발생시키는 T-SQL 트리거는 어떻습니까?


9

UPDATE 및 INSERT 에서 다른 테이블에 행을 추가 하는 테이블 트리거가 있습니다. 4 개의 열 중 하나가 변경된 경우에만 행을 추가하면됩니다. 변경 사항을 테스트하기 위해 IF UPDATE (col)을 사용해 보았지만 사각 지대가 있습니다. 그것은 단지 어떤 가치가 들어 왔는지를 테스트합니다. 나는 더 깊이 들어가야합니다. 나는 진정한 변화가 일어 났는지보기 위해 이전과 새로운 가치를 비교해야합니다. INSERT 및 UPDATE와 함께 작동해야합니다.

UPDATE의 경우 삽입 된 테이블과 삭제 된 테이블 모두 트리거 내에서 비교할 수있는 값을 가지고 있기 때문에 쉽습니다. 그러나 INSERT의 경우 삽입 테이블에만 값이 있습니다. 동일한 트리거 에서이 모든 것이 필요하기 때문에 해당 삽입 사례를 어떻게 처리합니까?

수정하려는 트리거 스크립트는 다음과 같습니다.

ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    -- Not all updates require a push
    IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
    BEGIN
        INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
                [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
            )
        SELECT  [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
        FROM inserted 
    END
END

2
"IF UPDATE (<column>)"사용에 대한 간단한 설명입니다. 값이 실제로 변경되었는지 여부에 관계없이 DML이 열의 값을 지정하면 true를 반환합니다.
Jonathan Fite

답변:


18

EXCEPT 세트 연산자를 사용하여 INSERT 및 UPDATE를 모두 처리 할 수 ​​있습니다. EXISTS는 단지 INSERT이거나 이러한 열에 대해 다른 값을 가진 UPDATE 인 경우에만 TRUE로 평가됩니다.

IF EXISTS (
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM inserted
           EXCEPT
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM deleted
          )
BEGIN...

이것은 다양한 열 업데이트 기능을 보는 것보다 훨씬 우아합니다. 우리는 프론트 엔드 코드와 이들을 결합하여 변경된 값만 보냅니다 (많은 조정 후). EXCEPT를 사용하면 훨씬 더 의미가 있습니다.
피터 쇼트

2
업데이트에서 2 개의 행이 "스왑"되는 경우에는 작동하지 않습니다. JobCodes를 업데이트해야하는 두 개의 John Smiths가있는 경우 (첫 번째 John은 1에서 2로, 두 번째 John은 2에서 1로) 업데이트가 수행되지 않았다고 말할 수 있습니다.
Steven Hibble

2
@StevenHibble-가능한 동안 어떻게 일어날 수 있습니까? 위의 Select 문에 PK 열을 포함시켜이 문제를 쉽게 해결할 수 있습니다.
채드 에스테스

1
확률은 데이터 소스와 잘못된 데이터 입력 가능성에 따라 다릅니다. "죄송합니다. 존 스미스 ..."는 결코 일어나지 않을 것 같습니다 . 어쨌든 이것은 다중 행 업데이트의 다른 절반을 해결하지 못합니다. 변경된 행만 삽입하는 방법은 무엇입니까? 이 EXISTS검사는 어떤 행 변경됨. 질문에서 삽입을 유지하면 의미있는 방식으로 하나만 변경되면 업데이트 된 모든 행을 기록합니다.
Steven Hibble

2

업데이트가 여러 행에 영향을 줄 수있는 경우 다음 두 가지 사항을 방지해야합니다.

  1. 유사한 행간에 값을 교환하는 업데이트를 고려하려고합니다. JobCodes를 업데이트해야하는 두 개의 John Smith가있는 경우 (첫 번째 John은 1에서 2로, 두 번째 John은 2에서 1로) 둘 다 업데이트되었다고주의해야합니다.
  2. 변경된 행만에 로그인하고 싶습니다 AT_Person_To_Push. 5 개의 행이 업데이트되었지만 관심있는 방식으로 2 개의 행만 업데이트되는 경우 2 개의 관련 행만 처리하면됩니다.

내가 처리하는 방법은 다음과 같습니다.

  1. 왼쪽 조인 inserteddeleted있기 때문에, inserted동시에 삽입 및 업데이트에 대한 행이됩니다 deleted만 업데이트 행이됩니다.
  2. 값과 값이 다른 행을 찾으려면 EXISTSwith EXCEPT를 사용하십시오 . 트리거가 INSERT를 처리 할 때 삭제 된 테이블이 비어 있고 LEFT JOIN이 널을 리턴하므로 사용할 수 없습니다 .inserteddeletedi.First_Name != d.First_Name OR i.Last_Name != d.Last_Name...
  3. 영향을받는 행만에 삽입하십시오 AT_Person_To_Push.
ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
            [Facility],
            [VendorID],
            [Person_code],
            [First_Name],
            [Last_Name],
            [JobCode],
            [Alink],
            [Inactive]
        )
    SELECT  i.[Facility],
            i.[VendorID],
            i.[Person_code],
            i.[First_Name],
            i.[Last_Name],
            i.[JobCode],
            i.[Alink],
            i.[Inactive]
    FROM inserted i
         LEFT JOIN deleted d
           ON i.Person_code = d.Person_code
    -- Check for changes that require a push
    WHERE EXISTS (SELECT i.[First_Name], i.[Last_Name], i.[JobCode], i.[Inactive]
                  EXCEPT
                  SELECT d.[First_Name], d.[Last_Name], d.[JobCode], d.[Inactive]);
END

1

이 시도,

Declare @Acton int=0

If exists (Select 1 from inserted)
set @Acton=1

If exists (Select 1 from deleted)
set @Acton=@Acton+2

if(@Action=1) -- Only insert

if(@Action=3) -- Only Update
begin
IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
Begin

End
end

if(@Action=2) -- Only Delete
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.