禁止在某些条件下插入表格

时间:2013-03-25 12:45:40

标签: sql database sql-server-2008 triggers insert-into

我有一个SQL Server 2008数据库。有三个端子连接(A,B,C)。数据库中有一个表SampleTable,它对任何终端活动做出反应。每次在任何终端上都有某些活动,登录到此数据库时,新行将插入SampleTable

我想将流量从三个终端中的一个(C)重定向到写入表RealTable而不是SampleTable,但我必须在DB层上执行此操作,因为将终端活动写入数据库的服务是在黑盒子中。

我已经使用重定向逻辑在SampleTable上运行了一些触发器,但问题是行仍在插入SampleTable

对此最干净的解决方案是什么?我确信在插入触发器中删除行是坏的,坏的,坏的。

请帮忙。

修改

我们当前的逻辑是这样的(这是伪代码):

ALTER TRIGGER DiffByTerminal
 ON SampleTable
AFTER INSERT
AS
DECLARE @ActionCode VARCHAR(3), 
    @ActionTime DATETIME,
    @TerminalId INT

  SELECT @ActionCode = ins.ActionCode, 
     @ActionTime = ins.ActionTime, 
     @TerminalId = ins.TerminalId
  FROM inserted ins

IF(@TerminalId = 'C')
BEGIN

    INSERT INTO RealTable 
    (   
         ...
    )
    VALUES
    (
         @ActionCode, 
         @ActionTime, 
         @TerminalId
    )
END

2 个答案:

答案 0 :(得分:3)

为了在行插入表之前“拦截”某些内容,您需要INSTEAD OF触发器,而不是AFTER触发器。因此,您可以删除现有的触发器(其中还包括假设所有插入都是单行的有缺陷的逻辑)并改为创建此INSTEAD OF触发器:

DROP TRIGGER DiffByTerminal;
GO

CREATE TRIGGER dbo.DiffByTerminal
 ON dbo.SampleTable
INSTEAD OF INSERT
AS
BEGIN
  SET NOCOUNT ON;

  INSERT dbo.RealTable(...) SELECT ActionCode, ActionTime, TerminalID
    FROM inserted
    WHERE TerminalID = 'C';

  INSERT dbo.SampleTable(...) SELECT ActionCode, ActionTime, TerminalID
    FROM inserted
    WHERE TerminalID <> 'C';
END
GO

这将处理单行插入和多行插入,包括(a)仅C(b)仅非C和(c)混合。

答案 1 :(得分:1)

最简单的解决方案之一是INSTEAD OF触发器。简单地说,触发器会“触发”您决定的动作,并让您“覆盖”动作的默认行为。

您可以使用INSTEAD OF触发器覆盖特定表/视图的INSERT,DELETE和UPDATE语句(使用组合来自不同表的数据并且您希望使视图可插入的视图),您可以在其中把你的逻辑。在触发器内部,您可以在适当的时候再次调用INSERT,并且您不必担心递归 - INSTEAD OF触发器不会应用于触发器代码本身内部的语句。

享受。