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

时间:2011-07-29 18:48:34

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

让我们说我有这样的查询:

SELECT * FROM 
(
  SELECT * FROM 
  (
    SELECT * FROM DB.dbo.Table
  )
  INNER JOIN DB.dbo.Table ON ...

我通过在任何地方手动更改字符串,使用不同的表多次运行此查询。我试着宣布以下内容:

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

但这似乎不起作用,因为它抛出一个错误,说我需要在我可以使用之前将@tablename声明为表变量。我如何模板化我的表名,如果可能的话,Intellisense仍然可以工作吗?

3 个答案:

答案 0 :(得分:7)

您可以将它包装在这样的EXEC语句中:

declare @my_tablename nvarchar(100) = 'mytable';
exec('
SELECT * FROM 
(
  SELECT * FROM 
  (
    SELECT * FROM ' + @my_tablename + '
  )
  INNER JOIN ' + @my_tablename + ' ON ...'
);

但不,intellisense在那种情况下不起作用。

如果您事先知道输出的样子,那么您可以声明一个临时表来保存结果,然后您可以在没有EXEC的情况下访问它。你将在临时表上有智能感知。

例如:

  --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

答案 1 :(得分:4)

没有。正如您不能将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#中一样,你会使用反射来进行动态运行时调用。

有关详细信息,请参阅The Curse and Blessings of Dynamic SQL

PS。将@tablename拆分为组件并使用QUOTENAME是绝对必须的,它可以防范SQL注入。使用PARSENAME为您进行拆分。

答案 2 :(得分:3)

您使用动态SQL。不知道为什么你需要这么多嵌套的SELECT,但它会是这样的:

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

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