INSTEAD OF 트리거의 식과 계산 열
뷰의 SELECT 목록에는 열 이름만으로 구성되는 단순 식이 아닌 다른 식이 포함됩니다. 뷰의 INSTEAD OF 트리거에는 INSERT 및 UPDATE에 지정된 값 중에서 기본 테이블 열에 설정해야 하는 값을 제대로 판단하는 논리가 있어야 합니다. 그러한 식의 예를 들면 다음과 같습니다.
- 상수 또는 몇몇 유형의 함수와 같이 테이블의 어떠한 열로도 매핑되지 않는 뷰 식
- 여러 열의 문자열을 연결하여 구성하는 복잡한 식과 같이 여러 열로 매핑되는 뷰 식
- 함수의 열을 참조하는 것과 같이 하나의 기본 테이블 열에 있는 값을 변환하는 뷰 식
이 문제는 뷰 열이 기본 테이블의 계산 열을 참조하는 단순 식인 경우에도 적용됩니다. 계산 열을 정의하는 식은 뷰 SELECT 목록의 더 복잡한 식과 같은 형식을 갖습니다.
뷰의 SELECT 목록에는 기본 테이블의 어떤 열에도 매핑되지 않는 식을 포함할 수 있습니다. 다음 예를 참조하십시오.
CREATE VIEW ExpressionView
AS
SELECT *, GETDATE() AS TodaysDate
FROM AdventureWorks.HumanResources.Employee
TodaysDate
열은 테이블 열에 매핑되지 않지만 SQL Server 2005에서는 ExpressionView
에 정의된 INSTEAD OF 트리거로 전달하는 inserted 테이블에 TodaysDate
열을 작성해야 합니다. 그러나 inserted.TodaysDate
열은 Null을 허용하므로 ExpressionView
를 참조하는 INSERT 문에서 이 열에 값을 제공하지 않아도 됩니다. 식은 테이블의 열로 매핑되지 않기 때문에 트리거가 INSERT 문에서 열에 제공한 값을 무시할 수 있습니다.
다른 열에 종속되지 않는 결과를 작성하는 기본 테이블의 계산 열을 참조하는 단순한 뷰 식인 경우에도 마찬가지입니다. 다음 예를 참조하십시오.
CREATE TABLE ComputedExample
(
PrimaryKey int PRIMARY KEY,
ComputedCol AS SUSER_NAME()
)
일부 복잡한 식은 여러 열로 매핑됩니다. 다음 예를 참조하십시오.
CREATE TABLE SampleTable
(
PriKey int,
FirstName nvarchar(20),
LastName nvarchar(30)
)
GO
CREATE VIEW ConcatView
AS
SELECT PriKey, FirstName + ' ' + LastName AS CombinedName
FROM SampleTable
ConcatView
의 CombinedName
식에는 FirstName
및 LastName
값의 연결 값이 있습니다. INSTEAD OF INSERT 트리거를 ConcatView
에 정의한 경우에는 INSERT 문에서 CombinedName
열에 값을 제공하는 방법에 대한 규칙이 있어야 합니다. 이 규칙은 트리거가 문자열 중 어느 부분을 FirstName
열에 지정하고 어느 부분을 LastName
열에 지정할 것인지 결정할 수 있도록 합니다. 'first_name;last_name' 규칙을 사용하여 INSERT 문에서 CombinedName
의 값을 지정하는 규칙을 선택하면 트리거에서 INSERT를 성공적으로 처리할 수 있습니다.
CREATE TRIGGER InsteadSample on ConcatView
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO SampleTable
SELECT PriKey,
-- Pull out the first name string.
SUBSTRING(
CombinedName,
1,
(CHARINDEX(';', CombinedName) - 1)
),
-- Pull out the last name string.
SUBSTRING(
CombinedName,
(CHARINDEX(';', CombinedName) + 1),
DATALENGTH(CombinedName) - (CHARINDEX(';', CombinedName) + 1)
)
FROM inserted
END
복잡한 식이 포함된 계산 열을 참조하는 단순 식인 뷰 열을 처리할 때도 비슷한 논리가 필요합니다.
일부 뷰 식은 수학적 연산을 수행하거나 열을 함수의 매개 변수로 사용함으로써 기본 테이블 열의 값을 변환할 수 있습니다. 이런 경우 INSTEAD OF INSERT 트리거의 논리에서 다음과 같은 두 가지 방식을 사용할 수 있습니다.
모든 INSERT 문에서 기본 테이블에 지정할 행 값을 제공하고 트리거 논리에서 inserted 테이블의 값을 기본 테이블로 이동하는 규칙을 사용합니다.
뷰의 SELECT에서 반환할 것으로 예상되는 값을 모든 INSERT 문에서 제공하는 규칙을 사용합니다. 이런 경우에는 논리에서 작업을 반대로 실행해야 합니다. 예를 들면 다음과 같습니다.
CREATE TABLE BaseTable ( PrimaryKey int PRIMARY KEY, ColumnB int, ColumnC decimal(19,3) ) CREATE VIEW SquareView AS SELECT PrimaryKey, ColumnB, -- Square the value of ColumnC SQUARE(ColumnC) AS SquareC FROM BaseTable CREATE TRIGGER SquareTrigger ON SquareView INSTEAD OF INSERT AS BEGIN INSERT INTO BaseTable SELECT PrimaryKey, ColumnB, -- Perform logical inverse of function in view. SQRT(SquareC) FROM inserted END
더하기 및 빼기와 같은 수학적 연산을 사용하는 복잡한 식과 같은 몇몇 식에서는 트리거에서 대상 기본 테이블 열에 대한 값을 확실하게 작성하는 데 사용할 수 있는 값을 제공하지 못할 수도 있습니다. 예를 들어 뷰 SELECT 목록에 IntColA + IntColB AS AddedColumns 식이 있을 경우 inserted.AddedColumns에 있는 값 10은 무엇을 의미하는지 생각해 봅시다. 10이 3 + 7, 2 + 8 또는 5 + 5 연산의 결과입니까? inserted.AddedColumns 값만으로는 IntColA 및 IntColB에 어떠한 값이 있는지 알 수 없습니다.
이런 경우 다른 정보 원본을 사용하도록 트리거의 코드를 작성하면 기본 테이블 열에 설정된 값을 알아낼 수 있습니다. 뷰에 INSTEAD OF 트리거가 있을 경우 뷰 SELECT 목록에는 트리거가 수정한 기본 테이블에서 Null이 아닌 모든 열에 대해 값을 작성할 수 있도록 충분한 정보가 포함되어야 합니다. 모든 데이터를 inserted 테이블에서 직접 가져오는 것은 아닙니다. inserted 테이블에 있는 값이 트리거가 다른 기본 테이블의 관련 데이터를 검색하는 데 사용하는 키 값이 되는 경우도 있습니다.