【问题标题】:How to do an insert in an update trigger?如何在更新触发器中插入?
【发布时间】:2017-11-11 10:39:13
【问题描述】:

我有一个UPDATE 触发器,它在将记录插入表中时发生,但我想在触发触发器的同时创建一个INSERT

原始 INSERT 将一条记录放入 BatchQueue 表中,当这种情况发生时,触发器被触发以更新第二个表 [Call]。

我希望能够在 BatchQueue 表中添加一条记录,该记录与插入的初始记录基本相似,但在时间列和另一列上有所不同。从技术上讲,我可以在原始插入上执行此操作,但仅当 SFlags = 11 时才需要执行 WHEN 或 IF

原来的INSERT语句:

BEGIN
    INSERT INTO BatchQueue (TimeToExecute, Operation, 
    Parameter,RuleID, FilterID, SFlags)
        SELECT @TimeToExecute, @Operation, @Parameter, @RuleID, @FilterID, 
        @SFlags FROM Call WHERE [ID]=@Parameter AND Active=0
               AND (OnlineCount>0 OR OnlineScreenCount>0 
       OR (Flags&POWER(2,26)=POWER(2,26)))  
 END

这是我想做的插入:

BEGIN
   INSERT INTO [dbo].[BatchQueue]
   VALUES(DateAdd(mi,2,getutcdate()),1,Call.ID,2,null,9,0,0,0)
   WHEN Call.SFlags = 11
END

触发语句:

BEGIN
IF @@ROWCOUNT > 0
BEGIN
   SET NOCOUNT ON
   UPDATE Call SET StoreReqCount = StoreReqCount + CallCount.actionCount
   FROM Call, (SELECT Parameter, [actionCount] = COUNT(*) FROM inserted 
   GROUP BY Parameter ) AS CallCount
   WHERE Call.ID = CallCount.Parameter
END

有人可以建议如何最好地做到这一点吗?我希望我已经澄清了。重申一下,要么使用 SFlags=11 的条件将第二个 INSERT 添加到第一个,要么使用触发器进行插入。哪个更好?

编辑:

尝试了以下方法:

   SELECT @StoreActionID = [ID] FROM BatchQueue 
   WHERE Parameter=@Parameter AND RuleID=@RuleID AND 
    SFlags=@SFlags
   IF @StoreActionID IS NOT NULL
   BEGIN
     UPDATE BatchQueue SET FilterID = @FilterID WHERE [ID] = 
     @StoreActionID
   END
ELSE
BEGIN
   INSERT INTO BatchQueue (TimeToExecute, Operation, Parameter, 
      RuleID, FilterID, SFlags)
        SELECT @TimeToExecute, @Operation, @Parameter, @RuleID, 
     @FilterID, @SFlags FROM Call WHERE [ID]=@Parameter AND Active=0
               AND (OnlineCount>0 OR OnlineScreenCount>0 OR 
     (Flags&POWER(2,26)=POWER(2,26))) --bit26 indicates META-DATA-ONLY
END
-- ADDED ADDITIONAL INSERT TO INSERT ACTION BASED ON STOREFLAGS 
BEGIN
    IF @SFlags = 11
    BEGIN 
        INSERT INTO BatchQueue (TimeToExecute, Operation, Parameter, 
        RuleID, FilterID, SFlags)
        SELECT @TimeToExecute, @Operation, @Parameter, @RuleID, 
        @FilterID, 9 FROM Call WHERE [ID]=@Parameter AND Active=0
               AND (OnlineCount>0 OR OnlineScreenCount>0 OR 
        (Flags&POWER(2,26)=POWER(2,26))) --bit26 indicates META-DATA-ONLY
    END        
END

【问题讨论】:

  • 请澄清您的问题。您是否希望修改您的 INSERT INTO [dbo].[BatchQueue] 语句以使某些值来自 Call 表?如果有,请说明逻辑。
  • 谢谢。我试图更清楚地重申这个问题
  • 您是否希望在 Call.SFlags = 11 时向 BatchQueue 插入第二条记录(行)?或修改现有记录?
  • 根据该条件在行中添加第二个。我尝试了一些东西,但没有奏效。现在将添加编辑。
  • 您有两个选择:在触发器中执行此操作,但您需要确保禁用直接触发器递归 (stackoverflow.com/a/1529516/6305294) - 如果其他代码依赖于它,可能会出现问题。

标签: sql sql-server


【解决方案1】:

您可以采用的一个不错的选择是编写存储过程,并在存储过程中包含原始 INSERT 语句,然后将特殊 INSERT 插入到与第一个 INSERT 相同的表中。但是,只有在第一次 INSERT 成功时才执行特殊的 INSERT。

让 UPDATE 通过您现有的触发器发生。如果它在生产中成功使用,您不想打扰触发器。

另外,如果您可以将这两个 INSERT 语句包装在一个事务中,那就太好了。

这将满足您的要求。

将以下 T-SQL 代码放入您的存储过程中

SET NOCOUNT ON;
BEGIN TRY

 Declare @insertedID int;

  --original INSERT
  INSERT INTO BatchQueue (TimeToExecute, Operation,
  Parameter, RuleID, FilterID, SFlags)
    SELECT
      @TimeToExecute,
      @Operation,
      @Parameter,
      @RuleID,
      @FilterID,
      @SFlags
    FROM Call
    WHERE [ID] = @Parameter
    AND Active = 0
    AND (OnlineCount > 0
    OR OnlineScreenCount > 0
    OR (Flags & POWER(2, 26) = POWER(2, 26));

  Set @insertedID = scope_identity() ;

  ---- INSERT if a row is successfully inserted
  IF @@ROWCOUNT > 0
  BEGIN

    INSERT INTO [dbo].[BatchQueue]
      SELECT DATEADD(mi, 2, GETUTCDATE()), 1, @parameter, 2, NULL, 9, 0, 0, 0)  
      WHERE @SFlags = 11;

  END

  --commit tran
  IF @@trancount > 0
  BEGIN
    COMMIT TRAN
  END

END TRY

BEGIN CATCH
  --get error details, which you can log to some table
  DECLARE @ErrorMessage nvarchar(4000);
  DECLARE @ErrorSeverity int;
  DECLARE @ErrorState int;

  SELECT
    @ErrorMessage = ERROR_MESSAGE(),
    @ErrorSeverity = ERROR_SEVERITY(),
    @ErrorState = ERROR_STATE();

  --roll back tran
  IF @@trancount > 0
  BEGIN
    ROLLBACK TRAN
  END

END CATCH

【讨论】:

  • 谢谢 Sunil,会试试这个。您将如何添加附加条件并更改插入以匹配原始插入,而不是使用所有预设值?例如我在编辑中:如果@SFlags = 11 我想添加 if Call.onlinescreencount > 0
  • 这似乎不起作用,我认为这与只允许单行插入有关。我已经更新了帖子,在存储过程中包含了我第一次没有包含的其他语句。
  • 这些变量来自哪里 - @TimeToExecute, @Operation, @Parameter, @RuleID, @FilterID, @SFlags and @Parameter?这些是您的存储过程的输入参数吗?
  • 另外,你能用更简单的条件代替(Flags & POWER(2, 26) = POWER(2, 26)))吗?
  • 我已经删除了按位运算符条件中的右括号。立即尝试查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 2016-10-13
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
相关资源
最近更新 更多