在SQL Server触发器中更改值时避免硬编码

时间:2009-05-14 08:34:53

标签: sql-server triggers

我有一个sql server“而不是insert”触发器,用于填充单个列(PromoCode)。这一切都很完美,但我不喜欢我必须在实际的INSERT语句中对列进行硬编码的事实:

CREATE TRIGGER PopulateOrderPromoCode ON Order
INSTEAD OF INSERT
AS BEGIN
    --// Get the Promo Code
    DECLARE @PromoCode int; 
    EXEC GetPromoCode @PromoCode OUTPUT;    

    --// Insert the order with the new Promo Code
    INSERT INTO Order (Id, CustomerId, PromoCode)
      SELECT Id, CustomerId, @PromoCode FROM inserted;
END

我更愿意只使用@PromoCode替换inserted.PromoCode中的值,然后可以使用:

INSERT INTO Order 
  SELECT * FROM inserted;

可以这样做吗?

3 个答案:

答案 0 :(得分:2)

不要使用INSTEAD OF INSERT触发器(你必须接管插入逻辑)

使用普通的INSERT触发器(除了插件外,还允许你做

这假设你可以插入没有促销代码(允许空值)或促销代码默认为某种东西。

CREATE TRIGGER PopulateOrderPromoCode ON Order
FOR INSERT
AS 
BEGIN
    --// Get the Promo Code
    DECLARE @PromoCode int;     
    EXEC GetPromoCode @PromoCode OUTPUT;        

    --// update the order with the new Promo Code
    UPDATE Order SET PromoCode = @PromoCode
      WHERE ID IN (SELECT ID FROM inserted)
END

答案 1 :(得分:0)

INSERTED是一个只读临时表,可以在任何触发器中访问。你不能修改它。

您使用INSERT的方式是最好的方法。所以,它没有任何问题。在执行INSERT时指定列是很好的(根据我的说法)。

答案 2 :(得分:-2)

动态SQL将是您唯一的其他选择。试试这个:

CREATE TRIGGER PopulateOrderPromoCode 
ON  Order
INSTEAD OF INSERT
AS 
BEGIN    
    --// Get the Promo Code    
    DECLARE @PromoCode int;         
    EXEC GetPromoCode @PromoCode OUTPUT;      

    DECLARE @InsertSQL nvarchar(2000), @SelectSQL nvarchar(2000)
    SET @InsertSQL = 'INSERT INTO Order ('
    SET @SelectSQL = 'SELECT '

    DECLARE @CurrentCol sysname
    SET @CurrentCol = ''



    WHILE EXISTS (  SELECT TOP 1 QUOTENAME(name)
                    FROM    sys.syscolumns 
                    WHERE   object_name(id) = 'Order'
                    AND     name <> 'PromoCode'
                    AND     name > @CurrentCol)
    BEGIN
        SET @CurrentCol = ( SELECT TOP 1 QUOTENAME(name)
                            FROM    sys.syscolumns 
                            WHERE   object_name(id) = 'Order'
                            AND     name <> 'PromoCode'
                            AND     QUOTENAME(name) > @CurrentCol
                            ORDER BY name)
        IF @CurrentCol IS NULL Break;

        SET @InsertSQL = @InsertSQL + @CurrentCol + ', '
        SET @SelectSQL = @SelectSQL + @CurrentCol + ', '
    END

    --Finish and concatenate the strings
    SET @InsertSQL = @InsertSQL + 'PromoCode) '
    SET @SelectSQL = @SelectSQL + '''' + @PromoCode + '''' + ' FROM INSERTED'

    DECLARE @MasterSQL nvarchar(2000)
    SET @MasterSQL = @InsertSQL + @SelectSQL

    EXEC (@MasterSQL)
END

BTW - “order”对于表名来说是一个糟糕的选择 - 它也是SQL中的保留字。尝试订单或OrderHeader。