2016-03-01 166 views
1

此代碼有什麼問題。插入更新後的SQL觸發器

如果我像這樣輸入

Declare tmp as CURSOR FOR 
Select i.ID from Inserted 
OPEN tmp 

或者如果我鍵入

Declare tmp as CURSOR FOR 
Select i.ID from Deleted 
OPEN tmp 

就像一個魅力,但

有什麼辦法,我可以寫這樣的事情

if @operation <> 3 

set @tmp = 'SELECT i.id FROM inserted i ' 

else 

set @tmp =' SELECT i.id FROM deleted i ' 

DECLARE tmpUpit CURSOR FOR 
@tmp 
OPEN tmpUpit 

編輯:

CREATE TRIGGER [dbo].[ax_Triger] ON [dbo].[extraTable] 
FOR INSERT, UPDATE, DELETE AS 

    SET NOCOUNT ON; 
--Capture the Operation (Inserted, Deleted Or Updated) 

    DECLARE @operation int 
    DECLARE @Count AS INT 

    SET @operation = 1 

    SELECT @Count = COUNT(*) 
    FROM DELETED 

    IF @Count > 0 
     BEGIN 
      SET @operation = 3 

      SELECT @Count = COUNT(*) 
      FROM INSERTED 

      IF @Count > 0 
      SET @operation = 2 
     END 
DECLARE tmpUpit CURSOR FOR 
SELECT i.id FROM inserted i 
OPEN tmpUpit 
FETCH NEXT FROM tmpUpit 
into @ID WHILE @@fetch_status = 0 

begin If Not exists 
(SELECT * FROM mytable 
where (Operation=3 OR (Operation=1 AND [email protected])) AND Status = 0 AND Tablename ='extraTable') 

begin INSERT INTO 
mytable ([Field1], [Field2], 
[ID], [Tablename], [Operation], [Time12], [Status]) 
VALUES (@Field1, @Field2, @ID, 'extraTable', @operation,GETDATE(),0) 

DELETE FROM mytable 
WHERE [Field1][email protected] And [Field2][email protected] And [ID][email protected] And [Tablename]='extraTable' 
AND [Operation] = 4 AND [Status] = 0 
End 
FETCH NEXT FROM tmpUpit into @ID 
End CLOSE tmpUpit DEALLOCATE tmpUpit end 

我需要從一個表中插入值到另一個根據有關插入/更新狀態/刪除

+2

爲什麼你想要一個遊標呢?他們效率非常低下。您嘗試的方法將無法正常工作,因爲您已經跨越到動態SQL地域。如果你可以發佈一些關於你的觸發器試圖做什麼的細節,我們可以幫助你找到一個不需要光標的基於集合的方法。 –

+0

@SeanLange我剛剛編輯..這是我的第一個觸發器 – myString

+0

@myString,你可以有條件地聲明它,你甚至可以將遊標變量作爲參數傳遞給SP。你不需要動態的sql。但不知何故,我認爲你需要'完全加入'。 –

回答

1

這是沒有經過充分測試,因爲貼在表的結構不匹配的貼觸發代碼。這至少應該證明你可以重新思考這個基於集合的邏輯,而不是通過激動的行來重新考慮行。

CREATE TRIGGER [dbo].[Trigger212] ON [dbo].[Towns] 
FOR INSERT, UPDATE, DELETE AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @operation int 
    DECLARE @Variable1 nvarchar(8) = 'Woof' 
    DECLARE @Variable2 nvarchar(4) = 'Foof' 

    --Capture the Operation (Inserted, Deleted Or Updated) 
    IF EXISTS(SELECT * FROM inserted) AND NOT EXISTS (SELECT * FROM deleted) 
     SET @operation = 1 --Insert 
    ELSE 
     IF EXISTS(SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted) 
      SET @operation = 2 --update 
     ELSE 
      SET @operation = 3 -- DELETE 

    INSERT Requests 
    (
     Field1 
     , Field2 
     , ID 
     , TableName 
     , Operation 
     , TimeU 
     , Status 
    ) 
    SELECT 'Woof' 
     , 'Foof' 
     , i.ID 
     , 'Towns' 
     , @operation 
     , GETDATE() 
     , 0 
    FROM inserted i 
    LEFT JOIN Requests r on r.ID = i.ID 
     AND r.Operation = 3 
      OR (r.Operation = 1 and r.ID = i.ID) 
     AND r.Status = 0 
     AND r.TableName = 'Towns' 
    WHERE r.ID IS NULL 

    DELETE r 
    FROM Requests r 
    JOIN inserted i on i.Field1 = r.Field1 
     AND i.Field2 = r.Field2 
     AND i.ID = r.ID 
     AND i.Operation <> @operation 
    WHERE r.TableName = 'Towns' 
     AND r.Status = 0 
END 

在一般情況下,我認爲應該避免觸發器,但他們有他們的位置。當觸發器合適時,我通常不會做這三種操作的狂熱粉絲。隨着時間的推移,它變得非常混亂,因爲你總是需要爲不同的操作做不同的邏輯。將它們分成三個觸發器使得這種可能性對於維護而言不那麼痛苦。