2010-09-01 64 views
2

查詢是 - 沒有用戶應該能夠更改產品表的價格。 msg將被顯示給用戶。所有試圖改變價格的嘗試都應該保存在臨時表中。保存更新在更新觸發器中的臨時表中的嘗試

如何解決這個問題在Sql server 2005中使用更新觸發器? 我試過如下。它按預期工作,但也顯示錯誤 -

事務在觸發器中結束。該批次已被中止。

ALTER TRIGGER tr_Products_U ON dbo.ProductDemo AFTER UPDATE 
AS 
    DECLARE @Data VARCHAR(200), 
      @sProductName NVARCHAR(40), 
      @mOldPrice MONEY, 
      @mNewPrice MONEY, 
      @ProductId int 

    IF UPDATE(ListPrice) 
    BEGIN 
     SELECT 
      @ProductId = d.ProductID,  
      @sProductName = d.Name, 
      @mOldPrice = d.ListPrice, 
      @mNewPrice = i.ListPrice 
     FROM 
      inserted i INNER JOIN deleted d ON i.ProductID = d.ProductID 

     SET @Data = 'Tried to update the price of ' + @sProductName 
      + ' [ProductID :' + CONVERT(VARCHAR(10), @ProductId) + '] ' 
      + ' from ' 
      + CONVERT(VARCHAR(10), @mOldPrice) 
      + ' to ' + CONVERT(VARCHAR(10), @mNewPrice) 

      print 'Can''t Change Price' 
         ROLLBACK TRAN 

         INSERT INTO #UpdateLIstPrices 
         VALUES (@Data);   
    END 
    RETURN 
GO 

回答

2

而不是寫這個作爲一個試圖回滾不良變化觸發後,我會處理這作爲記錄任何嘗試更新的價格,但允許更新到其他列的INSTEAD OF觸發器。

ALTER TRIGGER tr_Products_U ON dbo.ProductDemo INSTEAD OF UPDATE 
    AS 
     IF UPDATE(ListPrice) 
     BEGIN  
      PRINT 'Can''t Change Price' 

      INSERT INTO #UpdateLIstPrices 
       SELECT 'Tried to update the price of ' + d.Name 
         + ' [ProductID :' + CONVERT(VARCHAR(10), d.ProductId) + '] ' 
         + ' from ' 
         + CONVERT(VARCHAR(10), d.ListPrice) 
         + ' to ' + CONVERT(VARCHAR(10), i.ListPrice) 
        FROM inserted i 
         INNER JOIN deleted d 
          ON i.ProductID = d.ProductID 
     END 
     ELSE 
     BEGIN 
      UPDATE pd 
       SET Name = i.Name 
        /*, other columns as needed */ 
       FROM inserted i 
        INNER JOIN dbo.ProductDemo pd 
         ON i.ProductID = pd.ProductID 
     END 
     RETURN 
    GO 
+0

在[@bobs答案](http://stackoverflow.com/questions/3615951/save-update-attempts-in-temp-table-in-update-trigger/3621726#3621726),他是對於您嘗試記錄價格變化的問題絕對正確。我冒昧將他的修補程序納入上面的代碼中。 – 2010-09-01 20:29:49

1

您可以通過將您的UPDATE包裝在TRY/CATCH塊中來避免該錯誤消息。這也可以讓你報告你不想壓制的錯誤。例如,您可能想要嘗試以下操作:

BEGIN TRY 
    UPDATE ProductDemo 
    SET ListPrice = 100.00 
    WHERE ProductID = 3 
END TRY 

BEGIN CATCH 
    IF ERROR_NUMBER() <> 3609 
    BEGIN 
     DECLARE @errormessage nvarchar(500) 
     DECLARE @errorstate INT 
     DECLARE @errorseverity INT 

     SET @errormessage = 'Error ' + CAST(error_number() AS nvarchar) + ': ' + error_message() 
     SET @errorstate = error_state() 
     SET @errorseverity = error_severity() 

     RAISERROR (@errormessage, @errorseverity, @errorstate) 
    END 
END CATCH 

您確實觸發了另一個問題。它不預期多行更新與單個UPDATE語句的情況。將表格inserteddeleted中的列保存爲變量時,除了結果集中返回的最後一行外,您將丟失所有行中的信息。您可以使用單一的INSERT INTO... SELECT FROM聲明替換SELECTSETINSERT聲明以避免這種情況。

PRINT 'Can''t Change Price' 

INSERT INTO #UpdateLIstPrices 
SELECT 'Tried to update the price of ' + d.Name 
      + ' [ProductID :' + CONVERT(VARCHAR(10), d.ProductId) + '] ' 
      + ' from ' 
      + CONVERT(VARCHAR(10), d.ListPrice) 
      + ' to ' + CONVERT(VARCHAR(10), i.ListPrice) 
FROM inserted i 
INNER JOIN deleted d ON i.ProductID = d.ProductID 
+0

將+1插入到日誌表中。 – 2010-09-01 20:30:25

+0

哦.......感謝它的工作。這是我尋找的。 :) – Yogini 2010-09-07 01:55:28