열이 수정 된 경우에만 SQL 업데이트 트리거


101

다른 예를 살펴보면 다음과 같은 결과가 나왔지만 원하는대로 작동하지 않는 것 같습니다. QtyToRepair값이 업데이트 된 경우에만 수정 된 정보를 업데이트하고 싶습니다 ...하지만 그렇지 않습니다. 그.

내가 어디에 주석을 달면 모든 경우에 수정 된 정보가 업데이트됩니다. 내가 다른 예를 말했듯이 나는 낙관적이었다. 모든 단서 감사합니다. 감사.

월터

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    UPDATE SCHEDULE SET modified = GETDATE()
        , ModifiedUser = SUSER_NAME()
        , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S
    INNER JOIN Inserted I on S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    WHERE S.QtyToRepair <> I.QtyToRepair
END

8
경고 update()-열이 업데이트 목록에 나타나는지 테스트하고 삽입의 경우 항상 참입니다. 일부 값은 변경되고 일부는 변경되지 않은 행이 두 개 이상있을 수 있으므로 열 값이 변경되었는지 확인하지 않습니다.
Nikola Markovinović 2012 년

답변:


128

질문에는 두 가지 방법이 있습니다.

1- 트리거에서 업데이트 명령을 사용하십시오.

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
        ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END 
END

2- 삽입 된 테이블과 삭제 된 테이블간에 조인 사용

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;    

    UPDATE SCHEDULE 
    SET modified = GETDATE()
       , ModifiedUser = SUSER_NAME()
       , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S 
    INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber                  
    WHERE S.QtyToRepair <> I.QtyToRepair
    AND D.QtyToRepair <> I.QtyToRepair
END

테이블에 대해 업데이트 명령을 사용 SCHEDULE하고 QtyToRepair열을 새 값으로 설정하는 경우 새 값이 하나 또는 여러 행의 이전 값과 같으면 솔루션 1은 일정 테이블의 모든 업데이트 된 행을 업데이트하지만 솔루션 2는 이전 값이 새 값과 같지 않은 행만 업데이트합니다. 값.


SQLServer라고 언급하지 않아서 죄송합니다. 삭제 된 테이블을 사용해야했습니다. 나는 (역사를 유지하기 위해) 별도의 테이블에 쓰기를 끝냈습니다.
Walter de Jong

9
열이 동일한 값으로 변경되는 경우 트리거가 실행되지 않도록하려면 접근법 # 2가 더 좋습니다.
Neolisk 2015

2
내가 뭔가를 놓치고 있다고 생각하지만 # 1 접근 방식 은 업데이트 이후 이기 때문에 작동하지 않으므로 현재 행은 항상 삽입 행과 동일한 값을 갖습니다. 당신은 있어야 당신이 업데이트 후 사용하는 경우 삭제에 가입

5
@Rob "IF UPDATE"문은 쿼리의 일부로 업데이트 된 열 목록에 액세스 할 수있는 프로 시저를 호출하므로 이전 값을 알 필요가 없습니다. (우리는 단지 우리의 환경이 다 퉜다 및 확인이 "UPDATE는 경우"에 관계없이 "AFTER UPDATE"절의 영광)
TChadwick

3
inserted두 번째 쿼리에서 테이블 을 조인하는 이유는 무엇입니까? 테이블 자체와 같아야하지 않나요?
teran

22

fyi 내가 끝낸 코드 :

IF UPDATE (QtyToRepair)
    begin
        INSERT INTO tmpQtyToRepairChanges (OrderNo, PartNumber, ModifiedDate, ModifiedUser, ModifiedHost, QtyToRepairOld, QtyToRepairNew)
        SELECT S.OrderNo, S.PartNumber, GETDATE(), SUSER_NAME(), HOST_NAME(), D.QtyToRepair, I.QtyToRepair FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber 
        WHERE I.QtyToRepair <> D.QtyToRepair
end

1
위 의 2- Use Join between answer WHERE S.QtyToRepair <> I.QtyToRepair AND D.QtyToRepair <> I.QtyToRepair가 첫 번째 기준이 결코 참이 아니 었기 때문에 기준이 실행 되지 않거나 일치하지 않았기 때문에 이것이 도움이 되었습니다. 삽입 된 테이블은 항상 실제 테이블 값과 일치했습니다. `WHERE I.QtyToRepair <> D.QtyToRepair`를 사용하는 것이 저에게 핵심이었습니다. 또한 IF UPDATE (field)여러 트리거 의 도움이 발사됩니다.
Firegarden

13

QtyToRepair먼저 업데이트 되었는지 확인해야합니다 .

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
            ON S.OrderNo = I.OrderNo and S.PartNumber =    I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END

6

다음을 수행하려고합니다.

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;

    IF (UPDATE(QtyToRepair))
    BEGIN
        UPDATE SCHEDULE SET modified = GETDATE()
            , ModifiedUser = SUSER_NAME()
            , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo AND S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END

이 트리거는 값이 동일한 지 여부에 관계없이 열을 업데이트 할 때마다 실행됩니다.


2

레코드가 업데이트 될 때마다 레코드가 "삭제"됩니다. 내 예는 다음과 같습니다.

ALTER TRIGGER [dbo].[UpdatePhyDate]
   ON  [dbo].[M_ContractDT1]
   AFTER UPDATE
AS 
BEGIN
    -- on ContarctDT1 PhyQty is updated 
    -- I want system date in Phytate automatically saved
    SET NOCOUNT ON;

    declare @dt1ky as int   

    if(update(Phyqty))
    begin
        select @dt1ky = dt1ky from deleted

        update M_ContractDT1 set PhyDate=GETDATE() where Dt1Ky=  @dt1ky     

    end

END

잘 작동합니다

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