2015-01-07 1 views
5

많은 변수를 사용하지 않고이 업데이트 트리거를 어떻게 다시 작성합니까?첫 번째 T-SQL 업데이트 트리거를 최적화해야합니다.

나는 첫 번째 SQL Server 트리거를 작성했지만 제대로 작동하지만 더 쉬운 솔루션이 있어야한다고 생각합니다.

5 개의 열 중 최소 하나가 변경되면 다른 테이블에 2 개의 새 행을 씁니다. 행 1 = 이전 Fahrer (= 드라이버) 및 이전 dispodate 및 업데이트 시간 행 2 = 새 Fahrer 및 새로운 dispodate 및 updatedatetime 내 솔루션은 foxpro 트리거의 복사본 일 뿐이지 만 T에서 더 쉬운 솔루션이 있어야합니다 하나의 열이 변경되었는지 여부를 확인하는 -SQL

ALTER TRIGGER [dbo].[MyTrigger] 
ON [dbo].[tbldisposaetze] 
AFTER UPDATE 
AS 
SET NOCOUNT ON; 
/*SET XACT_ABORT ON 
SET ARITHABORT ON 
*/ 
DECLARE @oldfahrer varchar(10) 
DECLARE @oldbus varchar(10) 
DECLARE @olddispodat date 
DECLARE @oldvzeit decimal(4,0) 
DECLARE @oldbzeit decimal(4,0) 
DECLARE @oldbeschreibk varchar(255) 

DECLARE @newfahrer varchar(10) 
DECLARE @newbus varchar(10) 
DECLARE @newdispodat date 
DECLARE @newvzeit decimal(4,0) 
DECLARE @newbzeit decimal(4,0) 
DECLARE @newbeschreibk varchar(255) 

    SELECT @oldfahrer = fahrer,@oldbeschreibk=beschreibk,@oldbus=bus,@oldbzeit=bzeit,@olddispodat=dispodat,@oldvzeit=vzeit 
     FROM DELETED D 
    SELECT @newfahrer = fahrer,@newbeschreibk=beschreibk,@newbus=bus,@newbzeit=bzeit,@newdispodat=dispodat,@newvzeit=vzeit 
     FROM inserted I 

if @oldbeschreibk <> @newbeschreibk or @oldbus <> @newbus or @oldbzeit <> @newbzeit or @oldfahrer <> @newfahrer or @oldvzeit <> @newvzeit 
begin 
    IF (SELECT COUNT(*) FROM tbldispofahrer where [email protected] and [email protected]) > 0 
    update tbldispofahrer set laenderung = GETDATE() where [email protected] and [email protected] 
    else 
    INSERT into tbldispofahrer (fahrer,dispodat,laenderung) VALUES (@oldfahrer,@olddispodat,getdate()) 

    IF (SELECT COUNT(*) FROM tbldispofahrer where [email protected] and [email protected]) > 0 
    update tbldispofahrer set laenderung = GETDATE() where [email protected] and [email protected] 
    else 
    INSERT into tbldispofahrer (fahrer,dispodat,laenderung) VALUES (@newfahrer,@newdispodat,getdate()) 
end 
+1

확인이 먼저 모두 같은 변수를 사용해서는 안됩니다! 적 방아쇠를 당깁니다. 삭제되고 삽입 된 테이블은 여러 레코드를 포함 할 수 있으므로이를 고려해야합니다. – HLGEM

+0

방아쇠가 방아쇠를 당했을 때 ** 행에 한 번 ** ** 불리는 것으로 간주되는 ** 주요한 ** 결함 - ** 그렇지 않은 경우 **. 트리거는 ** 명령문 ** 당 한 번 실행됩니다. 따라서 UPDATE 문이 25 개의 행에 영향을 주면 트리거가 ** 한번 ** 발생하지만 Inserted와 Deleted는 각각 25 개의 행을 포함합니다 . 그 25 개의 행 중에서'SELECT' 코드가 선택됩니까 ?? 비 결정적입니다. 이것을 고려하려면 트리거를 다시 작성해야합니다! –

+0

'tbldispofahrer' 테이블의 기본 키 열은 무엇입니까? –

답변

4

SQL Server 2008 이상이 있다고 가정합니다. 변수없이 하나의 명령문에서이 모든 작업을 수행 할 수 있습니다.

먼저 변수를 가져와 일치하지 않는지 확인하기 위해 모든 작업을 수행하는 대신 where 절의 일부로 쉽게 수행 할 수 있습니다. 사람들이 코멘트에서 말했듯이 삽입 및 삭제의 일부로 여러 행을 가질 수 있습니다. 동일한 업데이트 된 행으로 작업하고 있는지 확인하려면 기본 키와 일치해야합니다.

행을 삽입하거나 업데이트하려면 MERGE 문을 사용하고 있습니다. 병합 원본은 위의 where 절이있는 유니온이며 유니온의 맨 위 테이블에는 이전 fahrer가 있고 맨 아래에는 새로운 farher가 있습니다. 내부 IF와 마찬가지로 기존 행이 멀리 떨어져 있고 dispodat에서 일치하고 적절하게 삽입되거나 업데이트됩니다.

예를 들어, newfahrer와 oldfahrer가 정확히 같을 수 있으므로 하나의 삽입 또는 업데이트가 발생해야합니다 (즉, bzeit 만 다른 경우). 노조는 중복 데이터가 삽입되는 것을 방지해야합니다. 나는 병합이 잘못되었다고 믿는다.

MERGE tbldispofahrer AS tgt 
USING (
    SELECT d.farher, d.dispodat, GETDATE() [laenderung] 
    INNER JOIN inserted i ON i.PrimaryKey = d.PrimaryKey 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreik ...) 
    UNION 
    SELECT i.farher, i.dispodat, GETDATE() [laenderung] 
    INNER JOIN inserted i ON i.PrimaryKey = d.PrimaryKey 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreik ...) 
) AS src (farher, dispodat, laenderung) 
ON tgt.farher = src.farher AND tgt.dispodat = src.dispodat 
WHEN MATCHED THEN UPDATE SET 
    laenderung = GETDATE() 
WHEN NOT MATCHED THEN 
    INSERT (fahrer,dispodat,laenderung) 
    VALUES (src.fahrer, src.dispodat, src.laenderung) 
1

다니엘의 답에는 약간의 구문 오류가 있습니다. 다음 코드는 잘 실행 :

MERGE tbldispofahrer AS tgt 
 
USING (
 
    SELECT d.fahrer, d.dispodat, GETDATE() [laenderung] from deleted d 
 
    INNER JOIN inserted i ON i.satznr = d.satznr 
 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreibk or i.bus <> d.bus or i.bzeit <> d.bzeit or i.vzeit <> d.vzeit) 
 
    UNION 
 
    SELECT i.fahrer, i.dispodat, GETDATE() [laenderung] from inserted i 
 
    INNER JOIN deleted d ON i.satznr = d.satznr 
 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreibk or i.bus <> d.bus or i.bzeit <> d.bzeit or i.vzeit <> d.vzeit) 
 
) AS src (fahrer, dispodat, laenderung) 
 
ON tgt.fahrer = src.fahrer AND tgt.dispodat = src.dispodat 
 
WHEN MATCHED THEN UPDATE SET 
 
    laenderung = GETDATE() 
 
WHEN NOT MATCHED THEN 
 
    INSERT (fahrer,dispodat,laenderung) 
 
    VALUES (src.fahrer, src.dispodat, src.laenderung);

관련 문제