Sql 有没有办法将表名指定为字符串?

Sql 有没有办法将表名指定为字符串?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,假设我有这样一个问题: SELECT * FROM ( SELECT * FROM ( SELECT * FROM DB.dbo.Table ) INNER JOIN DB.dbo.Table ON ... declare @my_tablename nvarchar(100) = 'mytable'; exec(' SELECT * FROM ( SELECT * FROM ( SELECT * FROM ' + @my_tablename +

假设我有这样一个问题:

SELECT * FROM 
(
  SELECT * FROM 
  (
    SELECT * FROM DB.dbo.Table
  )
  INNER JOIN DB.dbo.Table ON ...
declare @my_tablename nvarchar(100) = 'mytable';
exec('
SELECT * FROM 
(
  SELECT * FROM 
  (
    SELECT * FROM ' + @my_tablename + '
  )
  INNER JOIN ' + @my_tablename + ' ON ...'
);
我在不同的表中多次运行此查询,方法是在任何地方手动更改字符串。我试图声明以下内容:

DECLARE @tablename AS VARCHAR(255)
SET @tablename = 'DB.dbo.Table'

但这似乎不起作用,因为它向我抛出了一个错误,即我需要将
@tablename
声明为表变量,然后才能使用它。如何将我的表名模板化?如果可能的话,Intellisense还能工作吗?

您可以将其包装在EXEC语句中,如下所示:

SELECT * FROM 
(
  SELECT * FROM 
  (
    SELECT * FROM DB.dbo.Table
  )
  INNER JOIN DB.dbo.Table ON ...
declare @my_tablename nvarchar(100) = 'mytable';
exec('
SELECT * FROM 
(
  SELECT * FROM 
  (
    SELECT * FROM ' + @my_tablename + '
  )
  INNER JOIN ' + @my_tablename + ' ON ...'
);
但不,智能感知在这种情况下不起作用

如果您事先知道输出是什么样子的,那么您可以声明一个临时表来保存结果,然后您可以在不使用EXEC的情况下访问它。您将在临时表上显示intellisense

例如:

  --this must match whatever your SELECT is going to return
  CREATE TABLE #results(
    FIELD1 INT
   ,FIELD2 NVARCHAR(100)
   ,FIELD3 BIT
   );

EXEC('
  INSERT INTO #results(field1,field2,field3)
  SELECT FIELD1,FIELD2,FIELD3 FROM ' + @my_tablename
);

select * from #results  --you will have intellisense on #results

您可以使用动态SQL。不确定为什么需要这么多嵌套选择,但它可能类似于:

DECLARE @sql NVARCHAR(MAX) = N'SELECT ... FROM ' + @tablename + '...';
EXEC sp_executeSQL @sql;

但是,请注意SQL注入。不,IntelliSense无法解析对象名称的字符串(甚至无法在编辑对象名称时知道将出现什么)。

不。正如您无法在c#程序中将函数名称指定为字符串一样。T-SQL编译应该提供一个精确的访问计划,即打开和使用哪些索引来满足查询。为“字符串”制定计划是不可能的,就像在C#中不可能生成调用“字符串”作为方法的代码一样

解决方案是动态SQL:

declare @sql NVARCHAR(MAX) = N'SELECT ... FROM ' +
   quotename(@dbname) + N'.' + quotename(@schema) + N'.' + quotename(@table) + 
   N' WHERE ...';
exec sp_executesql @sql;
。。。就像在C#中一样,您可以使用反射来进行动态运行时调用

有关更多信息,请参阅


另外,将@tablename拆分为组件并使用是绝对必须的,它可以防止SQL注入。用于为您进行拆分。

+1对于链接,在处理动态SQL时,它始终是第一个要去的地方