2010-09-01 96 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