表变量在动态SQL中不起作用

时间:2012-02-22 03:35:48

标签: sql sql-server sql-server-2008 sql-server-2005

我的触发器如下,

Alter TRIGGER [dbo].[LogTable_InsertTrigger] on [dbo].[std_table]  AFTER  INSERT
as

    DECLARE  @ColName varchar(50), @QueryText nvarchar(max)

    declare @inserted  TABLE(
      [CountryID] [int] NOT NULL,
      [Country] [nvarchar](255) NOT NULL,
      [RegionId] [int] NULL
    )
    insert into @inserted
    select * from inserted

    DECLARE objCursor CURSOR FAST_FORWARD FOR
    select  ColName from dbo.getColumnNames('std_table')  

    OPEN objCursor 
    FETCH NEXT FROM objCursor INTO @ColName
    WHILE @@FETCH_STATUS = 0
    BEGIN
      set @QueryText= '
         insert into dbo.LogTable
         (StandardType,Attribute,Action,NEwValue,UserId,ModifiedDate)
        select ''Country'','''+@ColName+''',''Insert'','+@ColName+',1,getdate()
        from @inserted'

       EXEC sp_executesql   @QueryText  

       FETCH NEXT FROM objCursor INTO @ColName
    END
    CLOSE objCursor
    DEALLOCATE objCursor

当我尝试在DA Layer中插入表std_table时,我得到异常Must declare the table variable "@inserted"

我无法直接使用inserted表,因为我正在编写一个动态查询,其中魔术表不会工作。所以我试图将插入表中的数据转储到临时表并从中进行访问。

我试过

select * 
into #inserted
from inserted

这很有效,但由于许多用户通过网络访问我的应用程序,因此会导致数据问题。所以我不能用它。

1 个答案:

答案 0 :(得分:1)

这里有些不对劲。

  1. 这是一个表变量,而不是用户定义的表类型。
  2. 如果#temp表有效,为什么您认为这会导致多个用户出现数据问题?每个用户都将获得他们自己的#temp表版本。
  3. 如果您知道正好有三列并且您可以对表变量声明进行硬编码,那么为什么还需要动态生成三组插入?列名CountryID,Country,RegionID不是?
  4. 如果你真的需要动态地执行此操作,那么看起来你可以在没有显式游标的情况下更容易地做到这一点 - 不是这一定是一件坏事,或者它会执行比下面更糟糕的事情,但光标是更冗长,更丑陋的代码:

    ALTER TRIGGER [dbo].[LogTable_InsertTrigger] 
    ON [dbo].[std_table]  
    AFTER  INSERT
    AS
    BEGIN
      SET NOCOUNT ON;
    
      SELECT * INTO #t FROM inserted;
    
      DECLARE @sql NVARCHAR(MAX);
    
      SET @sql = N'';
    
      SELECT @sql = @sql + CHAR(13) + CHAR(10) + N'INSERT INTO dbo.LogTable
            (StandardType,Attribute,Action,NewValue,UserId,ModifiedDate)
            SELECT ''Country'','''+ColName+''',''Insert'','+ColName+',1,GETDATE() 
         FROM #t;'
      FROM dbo.GetColumnNames('std_table');
    
      EXEC sp_executesql @sql;
    END
    GO