Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to specify table name as a string?

Let us say I have a query like this:

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

I am running this query multiple times with different tables by manually changing the string everywhere. I tried declaring the following:

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

But this does not seem to work as it throws me an error saying that I need to declare @tablename as a table variable before I can use it. How do I templatize my table name and if that is possible, will Intellisense still work?

like image 339
Legend Avatar asked Jul 29 '11 18:07

Legend


People also ask

Can we pass table name as parameter in stored procedures?

The sp_executesql command supports accepting Table name as Parameter (Variable) in the following SQL Server versions i.e. 2000, 2005, 2008, 2008R2, 2012, 2014, 2017, 2019 and higher.

Can we give as table name in SQL?

You can rename a table or a column temporarily by giving another name known as Alias. The use of table aliases is to rename a table in a specific SQL statement. The renaming is a temporary change and the actual table name does not change in the database.


2 Answers

You can wrap it in an EXEC statement like this:

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

But no, intellisense will not work in that scenario.

If you know what your output will look like in advance, then you can declare a temp table to hold the results, and then you can access that without EXEC. You will have intellisense on the temp table.

For example:

  --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
like image 198
JosephStyons Avatar answered Nov 15 '22 09:11

JosephStyons


No. Just as you cannot specify the function name in your c# program as a string. T-SQL compilation is supposed to come up with a precise access plan, meaning what indexes to open and use to satisfy the query. It would be impossible to come up with a plan for a 'string', just as it would be impossible in C# to generate the code to invoke a 'string' as a method.

The solution is dynamic SQL:

declare @sql NVARCHAR(MAX) = N'SELECT ... FROM ' +
   quotename(@dbname) + N'.' + quotename(@schema) + N'.' + quotename(@table) + 
   N' WHERE ...';
exec sp_executesql @sql;

... just as in C# you would use reflection to do dynamic runtime invocation.

For more info see The Curse and Blessings of Dynamic SQL.

PS. the split of @tablename into components and the use of QUOTENAME is an absolute must, it guards agaisnt SQL Injection. Use PARSENAME to do the split for you.

like image 21
Remus Rusanu Avatar answered Nov 15 '22 09:11

Remus Rusanu