Sql 如何在作为变量传递的tablename上设置identity_insert

Sql 如何在作为变量传递的tablename上设置identity_insert,sql,sql-server,sql-server-2008,sql-server-2012,Sql,Sql Server,Sql Server 2008,Sql Server 2012,我在@strDBName中有数据库名称。我构建SET IDENTITY\u INSERT并执行它。没有错误,但后续插入失败。下面的代码说明了这个问题 Declare @Query Varchar(MAX) SET @Query = 'SET IDENTITY_INSERT '+ @strDBName +'..TableName ON' EXEC(@Query) INSERT INTO [TableName] ... (MAX) Value from another table

我在@strDBName中有数据库名称。我构建SET IDENTITY\u INSERT并执行它。没有错误,但后续插入失败。下面的代码说明了这个问题

  Declare @Query Varchar(MAX)
  SET @Query = 'SET IDENTITY_INSERT '+ @strDBName +'..TableName ON'
  EXEC(@Query)


  INSERT INTO [TableName] ... (MAX) Value from another table and other applicable record.


  SET @Query = 'SET IDENTITY_INSERT '+ @strDBName +'..TableName OFF'
  EXEC(@Query)

为了备份Brad在评论中给出的答案,这里有一个在单个动态查询中执行整个插入序列的MVCE。根据Kris的评论,请确保数据库名称为白名单,因为查询易受SqlInjection攻击。不幸的是,数据库名称无法通过sp_executesql在动态sql中参数化

鉴于:

CREATE TABLE TableName
(
    ID INT IDENTITY(1,1)
);
可以执行单个批次:

DECLARE @strDBName VARCHAR(100) = 'MyDatabase';
Declare @Query Varchar(MAX)
SET @Query = 'SET IDENTITY_INSERT '+ @strDBName +'..TableName ON; '
SET @Query = @Query + 'INSERT INTO '+ @strDBName 
 +'..[TableName](ID) SELECT COALESCE(MAX(ID), 0)+1 FROM '+ @strDBName +'..TableName; '
SET @Query = @Query + 'SET IDENTITY_INSERT '+ @strDBName +'..TableName OFF;'
EXEC(@Query)

我相信动态sql是在一个单独的会话中执行的。不过,您可以将这一切作为一条动态sql语句来实现,而且它应该可以工作。如果您需要di,则必须使用输出参数和sp_executesql来获取最大值。谢谢!如果要投入生产,我必须小心。这很容易受到SQL注入的攻击。我看到您是通过从另一个表中提取MAX来插入的。这有一种代码的味道,听起来您将在未来与并发性问题进行斗争。更不用说,如果您只是想从另一个表中插入值,那么使用identity似乎是个坏主意。为什么不把列设为int呢?insert语句也应该是动态sql。它没有数据库后缀。如果从sys.databases中的name=@strDBName begin退出select*,甚至可能会将整个内容包装起来。。。end为了防止错误的dbnames/sql注入每次调用EXECUTE时,它都会作为一个单独的批处理运行该命令,并具有自己的上下文,因此我们需要将所有内容都放在@Query中,只执行一次。谢谢斯图尔特!