DML 트리거 문은 삭제된 테이블과 삽입된 테이블이라는 두 개의 특수 테이블을 사용합니다. SQL Server는 이러한 테이블을 자동으로 생성하고 관리합니다. 이러한 임시 메모리 상주 테이블을 사용하여 특정 데이터 수정의 효과를 테스트하고 DML 트리거 작업에 대한 조건을 설정할 수 있습니다. 테이블의 데이터를 직접 수정하거나 테이블에서 인덱스 생성 등의 DDL(데이터 정의 언어) 작업을 수행할 수는 없습니다.
DML 트리거에서 삽입 및 삭제된 테이블은 주로 다음을 수행하는 데 사용됩니다.
테이블 간의 참조 무결성 확장.
뷰의 기초가 되는 기본 테이블에 데이터를 삽입하거나 업데이트.
오류를 테스트하고 오류에 따라 작업 수행.
데이터 수정 전과 후의 테이블 상태 차이를 찾아서 그 차이에 따라 작업 수행.
삭제된 테이블은 DELETE 및 UPDATE 문 중에 영향을 받는 행의 복사본을 저장합니다. DELETE 또는 UPDATE 문을 실행하는 동안 행은 트리거 테이블에서 삭제되고 삭제된 테이블로 전송됩니다. 삭제된 테이블과 트리거 테이블에는 일반적으로 공통된 행이 없습니다.
삽입된 테이블은 INSERT 및 UPDATE 문 중에 영향을 받는 행의 복사본을 저장합니다. 트랜잭션을 삽입하거나 업데이트하는 동안 삽입된 테이블과 트리거 테이블 모두에 새 행이 추가됩니다. 삽입된 테이블의 행은 트리거 테이블에 있는 새 행의 복사본입니다.
업데이트 트랜잭션은 삽입 작업 뒤에 있는 삭제 작업과 비슷합니다. 이전 행은 먼저 삭제된 테이블에 복사된 다음 새 행이 트리거 테이블과 삽입된 테이블에 복사됩니다.
트리거 조건을 설정할 때 트리거를 실행한 작업에 삽입 및 삭제된 테이블을 적절하게 사용. INSERT를 테스트할 때 삭제된 테이블을 참조하거나 DELETE를 테스트할 때 삽입된 테이블을 참조해도 오류가 발생하지 않지만, 이러한 경우 트리거 테스트 테이블에는 행이 포함되어 있지 않습니다.
비고
트리거 작업이 데이터 수정이 영향을 미치는 행 수에 따라 달라지는 경우 다중 행 데이터 수정(SELECT 문에 기반한 INSERT, DELETE 또는 UPDATE)에 대한 테스트(예: @@ROWCOUNT 검사)를 사용하고 적절한 조치를 취합니다.
SQL Server 2014는 AFTER 트리거에 대해 삽입 및 삭제된 테이블에서 text, ntext, 또는 image 열 참조를 허용하지 않습니다. 그러나 이러한 데이터 형식은 이전 버전과의 호환성을 위해서만 포함됩니다. 큰 데이터를 저장하는 데 선호되는 방법은 varchar(max), nvarchar(max), 및 varbinary(max) 데이터 유형을 사용하는 것입니다. AFTER 및 INSTEAD OF 트리거는 삽입된 테이블과 삭제된 테이블의 varchar(max), nvarchar(max), varbinary(max) 데이터를 모두 지원합니다. 자세한 내용은 CREATE TRIGGER(Transact-SQL)를 참조하세요.
트리거에 삽입된 테이블을 사용하여 비즈니스 규칙 적용 예제
CHECK 제약 조건은 열 수준 또는 테이블 수준 제약 조건이 정의된 열만 참조할 수 있으므로 모든 상호 테이블 제약 조건(이 경우 업무 규칙)을 트리거로 정의해야 합니다.
다음 예시는 DML 트리거를 생성합니다. 이 트리거는 PurchaseOrderHeader 테이블에 새 구매 주문서를 삽입하려고 시도할 때 공급업체의 신용 등급이 양호한지 확인합니다. 방금 삽입된 구매 주문에 해당하는 공급업체의 신용 등급을 가져오려면 Vendor 테이블이 참조되어 inserted 테이블과 조인되어야 합니다. 신용 등급이 너무 낮으면 메시지가 표시되고 삽입이 실행되지 않습니다. 이 예제에서는 다중 행 데이터 수정을 허용하지 않습니다. 자세한 내용은 여러 행의 데이터를 처리하기 위한 DML 트리거 만들기를 참조하세요.
USE AdventureWorks2012;
GO
IF OBJECT_ID ('Purchasing.LowCredit','TR') IS NOT NULL
DROP TRIGGER Purchasing.LowCredit;
GO
-- This trigger prevents a row from being inserted in the Purchasing.PurchaseOrderHeader table
-- when the credit rating of the specified vendor is set to 5 (below average).
CREATE TRIGGER Purchasing.LowCredit ON Purchasing.PurchaseOrderHeader
AFTER INSERT
AS
IF EXISTS (SELECT *
FROM Purchasing.PurchaseOrderHeader p
JOIN inserted AS i
ON p.PurchaseOrderID = i.PurchaseOrderID
JOIN Purchasing.Vendor AS v
ON v.BusinessEntityID = p.VendorID
WHERE v.CreditRating = 5
)
BEGIN
RAISERROR ('A vendor''s credit rating is too low to accept new
purchase orders.', 16, 1);
ROLLBACK TRANSACTION;
RETURN
END;
GO
-- This statement attempts to insert a row into the PurchaseOrderHeader table
-- for a vendor that has a below average credit rating.
-- The AFTER INSERT trigger is fired and the INSERT transaction is rolled back.
INSERT INTO Purchasing.PurchaseOrderHeader (RevisionNumber, Status, EmployeeID,
VendorID, ShipMethodID, OrderDate, ShipDate, SubTotal, TaxAmt, Freight)
VALUES (
2
,3
,261
,1652
,4
,GETDATE()
,GETDATE()
,44594.55
,3567.564
,1114.8638 );
GO
INSTEAD OF 트리거에서 삽입 및 삭제된 테이블 사용
테이블에 INSTEAD OF 트리거에 전달된 삽입 및 삭제된 테이블은 AFTER 트리거에 전달된 삽입 및 삭제된 테이블과 동일한 규칙을 따릅니다. 삽입 및 삭제된 테이블의 형식은 INSTEAD OF 트리거가 정의된 테이블의 형식과 동일합니다. 삽입 및 삭제된 테이블의 각 열은 기본 테이블의 열에 직접 매핑됩니다.
INSTEAD OF 트리거가 있는 테이블을 참조하는 INSERT 또는 UPDATE 문이 열 값을 제공해야 하는 경우와 관련된 다음 규칙은 테이블에 INSTEAD OF 트리거가 없는 경우와 동일합니다.
계산 열 또는 특정
timestamp데이터 형식이 있는 열에는 값을 지정할 수 없습니다.해당 테이블에 대해 IDENTITY_INSERT가 ON이 아닌 경우 IDENTITY 속성이 있는 열에는 값을 지정할 수 없습니다. IDENTITY_INSERT가 ON이면 INSERT 문이 값을 제공해야 합니다.
INSERT 문은 DEFAULT 제약 조건이 없는 모든 NOT NULL 열에 대해 값을 제공해야 합니다.
계산 열, ID 열, 또는
timestamp열을 제외한 모든 열의 경우, null을 허용하는 열이거나 DEFAULT 정의가 있는 NOT NULL 열에 대해서는 값이 선택 사항입니다.
INSERT, UPDATE 또는 DELETE 문이 INSTEAD OF 트리거가 있는 뷰를 참조하는 경우 데이터베이스 엔진은 테이블에 대해 직접 작업을 수행하는 대신 트리거를 호출합니다. 트리거는 뷰용으로 작성된 삽입 및 삭제된 테이블의 정보 형식이 기본 테이블의 데이터 형식과 다른 경우에도 기본 테이블에서 요청된 작업을 구현하는 데 필요한 모든 문을 작성하기 위해 삽입 및 삭제된 테이블에 제시된 정보를 사용해야 합니다.
뷰에 정의된 INSTEAD OF 트리거로 전달된 삽입 및 삭제된 테이블의 형식이 뷰에 대해 정의된 SELECT 문의 선택 목록과 일치합니다. 다음은 그 예입니다.
USE AdventureWorks2012;
GO
CREATE VIEW dbo.EmployeeNames (BusinessEntityID, LName, FName)
AS
SELECT e.BusinessEntityID, p.LastName, p.FirstName
FROM HumanResources.Employee AS e
JOIN Person.Person AS p
ON e.BusinessEntityID = p.BusinessEntityID;
이 보기에 대한 결과 집합에는 int 열 하나와 nvarchar 열 두 개, 총 세 개의 열이 있습니다. 뷰에 정의된 INSTEAD OF 트리거에 전달된 삽입 및 삭제된 테이블에는 int라는 열, BusinessEntityID라는 열, nvarchar라는 열이 있으며 LName라는 열, 또한 nvarchar라는 열 및 FName라는 열이 포함됩니다.
뷰의 선택 목록에는 단일 기준 테이블 열에 직접 매핑되지 않는 식도 포함될 수 있습니다. 상수 또는 함수 호출과 같은 일부 뷰 식은 열을 참조하지 않을 수 있으며 무시할 수 있습니다. 복잡한 식은 여러 열을 참조할 수 있지만 삽입 및 삭제된 테이블에는 삽입된 각 행에 대해 하나의 값만 있습니다. 뷰의 간단한 표현식이 복잡한 식을 가진 계산된 열을 참조하는 경우에도 동일한 문제가 적용됩니다. 뷰의 INSTEAD OF 트리거는 이러한 유형의 식을 처리해야 합니다.