让我们说我有这样的查询:
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仍然可以工作吗?
答案 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无法解析对象名称的字符串(或者甚至在编辑将要存在的对象名称时知道)。