MS SQL Server 2008 R2에서 실행중인 삽입/업데이트를 무언가를 검사하고 허용 또는 롤백 (raiserror
통해)하는 사전 삽입 및 사전 업데이트 트리거가 필요합니다.트리거에서 롤백 트랜잭션
질문 : INSTEAD OF
에서 트리거합니다. 실제로 삽입 또는 업데이트를 명시 적으로 작성해야합니까? 기본 삽입 또는 업데이트를 수행하고 "사전 검사"만 수행하기를 원하기 때문입니다.
MS SQL Server 2008 R2에서 실행중인 삽입/업데이트를 무언가를 검사하고 허용 또는 롤백 (raiserror
통해)하는 사전 삽입 및 사전 업데이트 트리거가 필요합니다.트리거에서 롤백 트랜잭션
질문 : INSTEAD OF
에서 트리거합니다. 실제로 삽입 또는 업데이트를 명시 적으로 작성해야합니까? 기본 삽입 또는 업데이트를 수행하고 "사전 검사"만 수행하기를 원하기 때문입니다.
예.
INSERT
또는 UPDATE
을 명시 적으로 써야합니다.
트리거는 INSTEAD OF
DML 작업을 실행합니다. 트리거를 비워두면 INSERTED
/DELETED
테이블이 생성되어 tempdb
에 채워진 것 외에는 아무런 작업도 수행되지 않습니다.
의견에서 논의했지만 트리거를 전혀 사용하지 않지만 고유 한 필터링 된 인덱스 CREATE UNIQUE INDEX ix ON T(a,b,c) WHERE c <> ''
을 사용합니다. 이것은 동시성을 다룰 때 잠재적 인 논리 문제를 피하고 성능이 더 좋아질 수 있습니다.
감사합니다. DML 작업에서 삽입되고 업데이트 된 행의 별칭은 무엇입니까? – Cartesius00
@James -'INSERTED'와'DELETED'하지만 이것들은 테이블이 아닙니다. 트리거는 명령문 당 한 번 실행됩니다. 그래서 INSERT INTO YourTable SELECT * FROM INSERTED는 전형적인'INSERT' 트리거가 될 것입니다. –
그리고'YourTable'에 ID 열과 많은 다른 많은 열이 포함되어 있다면? 'SELECT *'는 문제입니다. 그렇죠? – Cartesius00
실제 삽입 또는 업데이트를 바꾸지 않으려면 INSTEAD OF
트리거를 원하지 않을 것입니다. 귀하의 경우 대신 FOR INSERT, UPDATE
트리거가 필요합니다.
이 예제 트리거는 누군가가 titles 테이블에 데이터를 추가하거나 변경하려고 시도 할 때 클라이언트에 메시지를 인쇄합니다.
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'reminder' AND type = 'TR')
DROP TRIGGER reminder
GO
CREATE TRIGGER reminder
ON titles
FOR INSERT, UPDATE
AS RAISERROR ('inserts and updates to the titles table is not allowed', 16, 1)
GO
또한 IF EXISTS
또는 COLUMNS_UPDATED
뿐만 아니라 같은 것들을 사용할 수 있습니다.
여기서 롤백을 사용하는 또 다른 예입니다. 당신이 거래를하거나하지 않을 경우
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'employee_insupd' AND type = 'TR')
DROP TRIGGER employee_insupd
GO
CREATE TRIGGER employee_insupd
ON employee
FOR INSERT, UPDATE
AS
/* Get the range of level for this job type from the jobs table. */
DECLARE @min_lvl tinyint,
@max_lvl tinyint,
@emp_lvl tinyint,
@job_id smallint
SELECT @min_lvl = min_lvl,
@max_lvl = max_lvl,
@emp_lvl = i.job_lvl,
@job_id = i.job_id
FROM employee e INNER JOIN inserted i ON e.emp_id = i.emp_id
JOIN jobs j ON j.job_id = i.job_id
IF (@job_id = 1) and (@emp_lvl <> 10)
BEGIN
RAISERROR ('Job id 1 expects the default level of 10.', 16, 1)
ROLLBACK TRANSACTION
END
ELSE
IF NOT (@emp_lvl BETWEEN @min_lvl AND @max_lvl)
BEGIN
RAISERROR ('The level for job_id:%d should be between %d and %d.',
16, 1, @job_id, @min_lvl, @max_lvl)
ROLLBACK TRANSACTION
END
는 잘 모르겠지만, 귀하의 경우 다음과 같이 할 것입니다 :
USE myDatabase
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'myTable' AND type = 'TR')
DROP TRIGGER tr_myTrigger
GO
CREATE TRIGGER tr_myTrigger
ON myTable
FOR INSERT, UPDATE
AS
if(exists(select * from inserted where rtrim(c) <> ''))
begin
-- check to make sure the insert(s) are unique
if(exists(
select * from inserted i
join dbo.myTable t on i.a = t.a and i.b = t.b and i.c = t.c)
begin
raiserror('Duplicate(s) found', 16, 1)
rollback transaction
end
end
은 "PreCheck를"의 본질은 무엇인가? 트리거에는'inserted' /'deleted' 테이블을 관리하는 오버 헤드가 있습니다. 그것은 다른 방식으로 집행 될 수있는 것입니까? –
우리가 필요로하는 것은 하나의 열에서 빈 문자열을 무시하는 트리플 (3 개 열)에 대한 고유 한 제한 조건입니다. – Cartesius00
튜플'(a, b, c)'의 경우'c'가 빈 문자열 값을 가지면 고유 한 제약 조건을 위해 해당 튜플을 완전히 무시하고 싶습니까? –