누가 레코드를 삭제했는지 알 수 있도록 삭제 트리거에 정보를 전달하는 방법이 있습니까?
예 :라는 매우 시원하고 기능이 부족한 기능을 사용합니다 CONTEXT_INFO
. 본질적으로 모든 범위에 존재하며 트랜잭션에 의해 제한되지 않는 세션 메모리입니다. 서브 프로세스 / EXEC 호출 사이에서 앞뒤로 트리거하기 위해 정보 (모든 정보-제한된 공간에 맞는 정보)를 전달하는 데 사용할 수 있습니다. 그리고 나는이 똑같은 상황을 위해 그것을 전에 사용했습니다.
작동 방식을 확인하려면 다음을 테스트하십시오. CHAR(128)
이전으로 변환 중 CONVERT(VARBINARY(128), ..
입니다. 이것은 빈 패딩을 강제로 빼기 위해 s로 오른쪽이 채워져 있기 때문에 쉽게 VARCHAR
꺼낼 수 있도록합니다 .CONTEXT_INFO()
VARBINARY(128)
0x00
SELECT CONTEXT_INFO();
-- Initially = NULL
DECLARE @EncodedUser VARBINARY(128);
SET @EncodedUser = CONVERT(VARBINARY(128),
CONVERT(CHAR(128), 'I deleted ALL your records! HA HA!')
);
SET CONTEXT_INFO @EncodedUser;
SELECT CONTEXT_INFO() AS [RawContextInfo],
RTRIM(CONVERT(VARCHAR(128), CONTEXT_INFO())) AS [DecodedUser];
결과 :
0x492064656C6574656420414C4C20796F7572207265636F7264732120484120484121202020202020...
I deleted ALL your records! HA HA!
함께 모아서:
앱은 레코드를 삭제하는 UserName (또는 기타)을 전달하는 "삭제"저장 프로 시저를 호출해야합니다. 이미 삽입 및 업데이트 작업을 추적하는 것처럼 들리기 때문에 이미 사용중인 모델이라고 가정합니다.
"삭제"저장 프로시 저는 다음을 수행합니다.
DECLARE @EncodedUser VARBINARY(128);
SET @EncodedUser = CONVERT(VARBINARY(128),
CONVERT(CHAR(128), @UserName)
);
SET CONTEXT_INFO @EncodedUser;
-- DELETE STUFF HERE
감사 트리거는 다음을 수행합니다.
-- Set the INT value in LEFT (currently 50) to the max size of [UserWhoMadeChanges]
INSERT INTO AuditTable (IdOfRecordedAffected, UserWhoMadeChanges)
SELECT del.ID, COALESCE(
LEFT(RTRIM(CONVERT(VARCHAR(128), CONTEXT_INFO())), 50),
'<unknown>')
FROM DELETED del;
@SeanGallardy가 주석에서 지적했듯이이 테이블에서 레코드를 삭제하는 다른 프로 시저 및 / 또는 임시 쿼리로 인해 다음 중 하나 일 수 있습니다.
CONTEXT_INFO
설정되지 않았으며 여전히 남아 있습니다 NULL
.
이러한 이유로 나는 기본값 INSERT INTO AuditTable
을 사용하기 COALESCE
위해 위의 내용 을 업데이트했습니다 . 또는 기본값을 원하지 않고 이름이 필요한 경우 다음과 유사한 작업을 수행 할 수 있습니다.
DECLARE @UserName VARCHAR(50); -- set to the size of AuditTable.[UserWhoMadeChanges]
SET @UserName = LEFT(RTRIM(CONVERT(VARCHAR(128), CONTEXT_INFO())), 50);
IF (@UserName IS NULL)
BEGIN
ROLLBACK TRAN; -- cancel the DELETE operation
RAISERROR('Please set UserName via "SET CONTEXT_INFO.." and try again.', 16 ,1);
END;
-- use @UserName in the INSERT...SELECT
CONTEXT_INFO
유효한 UserName 이 아닌 값으로 설정 되었으므로 AuditTable.[UserWhoMadeChanges]
필드 크기를 초과 할 수 있습니다 .
이런 이유로 나는 LEFT
움켜 잡은 것이 무엇이든 CONTEXT_INFO
깨지지 않도록 하는 기능을 추가했습니다 INSERT
. 코드에서 언급했듯이 필드 50
의 실제 크기 로 설정하면 됩니다 UserWhoMadeChanges
.
SQL Server 2016 이상 업데이트
SQL Server 2016은 세션 별 메모리의 향상된 버전 인 세션 컨텍스트를 추가했습니다. 새로운 세션 컨텍스트는 본질적으로 "Key"유형 sysname
(즉 NVARCHAR(128)
)이고 "Value" 인 키-값 쌍의 해시 테이블입니다 SQL_VARIANT
. 의미:
- 이제 값이 분리되어 다른 용도와 충돌 할 가능성이 줄어 듭니다.
- 다양한 유형을 저장할 수 있으며 더 이상 값을 가져올 때 이상한 동작에 대해 걱정할 필요가 없습니다
CONTEXT_INFO()
(자세한 내용은 내 게시물을 참조하십시오 : CONTEXT_INFO ()가 SET CONTEXT_INFO에 의해 설정된 정확한 값을 반환하지 않는 이유는 무엇입니까? )
- 당신이 얻을 훨씬 더 많은 공간을 : 8000 "값"당 최대 바이트, 최대 모든 키에서 256킬로바이트의 총 (128 비교하는 것은의 최대 바이트
CONTEXT_INFO
)
자세한 내용은 다음 설명서 페이지를 참조하십시오.
SUSER_SNAME()
기록을 삭제 한 사람을 얻는 열쇠입니다.