创建触发数据的临时表

时间:2011-03-22 11:33:13

标签: sql sql-server-2008 triggers

我正在尝试创建一个审核触发器,而不必多次指定列列表。

为此,我想在触发器中生成INSERTED或DELETED数据内容的临时表,然后将其处理到审计表中。

如果我使用它:

IF @ChangeType = 'D'
  SELECT * INTO #tmp FROM DELETED
ELSE
  SELECT * INTO #tmp FROM INSERTED

然后我在第二个SELECT * INTO中得到一个编译错误,表#tmp已经存在。

如果我尝试使用动态SQL解决此问题:

SET @Sql = 'SELECT * INTO #tmp FROM '
IF @ChangeType = 'D'
   SET @Sql = @Sq + 'DELETED'
ELSE
   SET @Sql = @Sql + 'INSERTED'

EXEC (@Sql)

然后我收到DELETED和INSERTED表不存在的错误。

如何将触发器中的INSERTED和DELETED表转换为临时表或其他内存表?

3 个答案:

答案 0 :(得分:4)

尝试在if之外创建临时表,例如:

SELECT TOP 0 * INTO #tmp FROM DELETED

IF @ChangeType = 'D'
  INSERT INTO #tmp SELECT * FROM DELETED
ELSE
  INSERT INTO #tmp SELECT * FROM INSERTED

答案 1 :(得分:1)

由于临时表对象的解析解析,这是一个已知问题。在同一范围内有两个SELECT-INTO语句,SQL Server就是这样做的。

SELECT * INTO #tmp FROM DELETED WHERE 1=0
IF @ChangeType = 'D'
  INSERT #tmp SELECT * FROM DELETED
ELSE
  INSERT #tmp SELECT * FROM INSERTED

答案 2 :(得分:0)

我很感兴趣为什么你需要首先将数据复制到另一个表中。但是,那是偏离主题的......

临时表(#temp)在逻辑上存储在光盘上,而表变量(@temp)在逻辑上仅在内存中,对于小任务可能更为理想。 (假设写入表通常只会影响少量行。)

但是,可以使用SELECT INTO技巧创建临时表,从而无需事先知道表定义。

但是,如果您事先知道了表格定义,那么您不能简单地使用以下内容吗?

DECLARE @temp TABLE (id AS INT, val as INT)

IF @ChangeType = 'D'
   INSERT INTO @temp SELECT * FROM DELETED
ELSE
   INSERT INTO @temp SELECT * FROM INSERTED


就个人而言,如果可能,我甚至会避免使用*。您的后续查询将仅使用特定字段,因此我只复制我正在使用的字段。这样做的另一个好处是,如果将字段添加到表中,则代码不会中断...

DECLARE @temp TABLE (id AS INT, val as INT)

IF @ChangeType = 'D'
   INSERT INTO @temp SELECT id, val FROM DELETED
ELSE
   INSERT INTO @temp SELECT id, val FROM INSERTED


在我看来,指定字段(这是您希望避免的)的优点是,您可以确保始终只复制您需要的字段。