2017-05-13 2 views
2
CREATE TRIGGER T 
ON TABLE_2 
AFTER INSERT 
AS 
    DECLARE @bought_t int, 
      @name_t varchar(20) 

    SELECT @name_t = name_t 
    FROM inserted 

    SELECT @bought_t = bought_t 
    FROM TABLE_1 
    WHERE name_t = @name_t 

    IF @bought_t < 100 
    BEGIN 
     UPDATE TABLE_1 
     SET bought_t = @bought_t + 1 
     WHERE TABLE_1.name_t = @name_t 
    END 
    ELSE 
     ROLLBACK TRANSACTION 

열 (TABLE_1) 'TABLE_2'에서 삽입이 일어난 후 업데이트를 만들고 있는데, 50과 100 사이의 값을 유지해야합니다.이 트리거가 전문적이고 최적화되어 있는지 그것은 수? 또는 버그/보안 문제로 이어질 수있는 몇 가지 결함이 있습니다.트리거를 최적화하는 방법은 무엇입니까?

+3

방아쇠 방아쇠가 ** 주 ** 당신은 그것이 행 ** 당 ** 한 번 ** ** 전화 **라고 생각하는 것으로 보인다 ** ** ** 경우입니다. 트리거는 ** 명령문 ** 당 한 번 실행됩니다. 따라서이 트리거로 인해 발생하는 INSERT 문이 25 개의 행을 삽입하면 ** 한 번 ** 트리거가 발생하지만'Inserted' 의사 테이블은 25 개의 행을 포함합니다. 다음 25 개의 행 중 어느 것이 귀하의 코드에서 선택됩니까? 'SELECT @name_t = name_t FROM inserted' - 비 결정적이므로 ** 임의의 한 행 **을 가져오고 ** 다른 모든 행은 무시합니다 **. 이것을 고려하려면 트리거를 다시 작성해야합니다! –

+0

거래에 있음을 어떻게 알 수 있습니까? 'else into rollback '을 사용하면'insert into' TABLE_2가 트랜잭션으로 시작하지 않을 때 트리거가'rollback' 코드를 실행하면 오류가 발생합니다. 또한 그 밖의 무엇이 롤백되는지 어떻게 알 수 있습니까? 다른 누군가가 코드를 작성한 경우,'bought_t '값이> = 100 일 때 왜 변경 사항이 롤백되는지 알 수 있습니까? 그리고 더 많은 정보없이 최적화 된 것인지 말할 수 없습니다. 우선, SSMS의 트리거에서'update' 문을 실행하고 쿼리 계획을 캡처해야합니다. 그게 너 한테 많이 말해 줄거야. –

+0

@marc_s 사실. 'A', B '), ('B ','Z '), ('S ','A '), ('A ', B' ','S '), ('D ','G ')' 그리고 한 번만 실행되는 업데이트 기능이 있습니다. – user3832856

답변

1

기본적으로, 당신이되고 완전히 트리거를 다시 작성해야 세트 기반여러 행 Inserted 의사 테이블에에 대한 작업을 수행 할 수 있습니다.

-- create the two tables 
CREATE TABLE TABLE_2 (ID INT NOT NULL IDENTITY(1,1), ProdName VARCHAR(50)) 
CREATE TABLE TABLE_1 (ProdName VARCHAR(50), Bought INT) 
GO 

-- create trigger on "TABLE_2" to update "TABLE_1"  
CREATE TRIGGER T2Insert 
ON TABLE_2 
AFTER INSERT 
AS 
    UPDATE T1 
    SET Bought = Bought + 1 
    FROM TABLE_1 T1 
    INNER JOIN Inserted i ON T1.ProdName = i.ProdName 
    WHERE T1.Bought < 100 
GO 

-- initialize TABLE_1 with some seed data 
INSERT INTO dbo.TABLE_1 (ProdName, Bought) 
VALUES ('Prod1', 0), ('Prod2', 20), ('Prod3', 40), ('Prod4', 40), ('Prod100', 100) 

-- insert new values into TABLE_2 
INSERT INTO dbo.TABLE_2 (ProdName) 
VALUES ('Prod1'), ('Prod100'), ('Prod2'), ('Prod4') 

-- get data to check 
SELECT * FROM dbo.TABLE_1 

이 출력을 렌더링 :

CREATE TRIGGER T 
ON TABLE_2 
AFTER INSERT 
AS 
    UPDATE T1 
    SET bought_t = bought_t + 1 
    FROM TABLE_1 T1 
    INNER JOIN Inserted i ON i.name_t = T1.name_t 
    WHERE T1.bought_t < 100 

UPDATE : 이것을 증명하기 위해 데모 작동

- 내 의견 - 이런 식으로 뭔가를 시도

다행히도, 그 또한 쉽게

enter image description here

당신은 쉽게 볼 수 있듯이 :

또한 삽입 된 값 Bought
  • Prod100의 업데이트가 하지 원인을 Bought
  • 의 업데이트를 한 원인이 삽입 된
    • Prod1, Prod2, Prod4

      UPDATE # 2 : 여러 개의 동일한 값을 동시에 삽입해야하는 경우 다음과 같이 트리거를 약간 향상시켜야합니다.

    +0

    @'buy_t'가 단순히''buy_t'일까요? –

    +0

    @JamesL .: 예 - 물론 - 복사 및 붙여 넣기 오류 - 고침, 고마워요! –

    +0

    이렇게하면 한 번만 업데이트 할 수 있습니다. 위의 주석에서 주어진 값을 삽입하면, '(1 행 영향을 받음) (5 행이 영향을 미침)'트리거가 5 대신에 한 번만 업데이트됩니다. – user3832856

    관련 문제