3

Please guide me how to create table variables dynamically. I know it can be like this:

DECLARE @people TABLE 
( 
    id INT, 
    name VARCHAR(32) 
);

How I will create if dont know columns and data types. Scenario is I have to create table variable as per a physical tables and selct data into them, use them in SP and then return data in table variables to C# program.

For example I have a table Employees. I want create a table variable with same structure as Employyes have. But mentioning columns take a lot time (as Employees have about 100 columns)

Please advice.

user576510
  • 5,777
  • 20
  • 81
  • 144
  • 1
    Please explain what you mean. Your question is not clear. – Oded Sep 04 '11 at 16:24
  • Oded please see my question, I have edited it. Thanks – user576510 Sep 04 '11 at 16:25
  • 4
    Why do you need a table variable? The problem is going to be one of scope. If you just need to generate a query dynamically, use dynamic SQL, not sure why you need a table variable if you're just going to return the results to C#. If you don't know the columns and data types, how is your C# code going to consume the result? – Aaron Bertrand Sep 04 '11 at 16:34
  • Aaron Bertrand, as I mentioned I will keep data in it and use it for 2 purposes, in a subquery and for sending data to C#. As I mentioned I know table structre but I want to know can I create a table variable dynamcially as per a physical table ? My table has a lot of columns and it is time taking to write structure. Thanks – user576510 Sep 04 '11 at 16:38
  • Also can you please specify what version of SQL Server you are using. – Aaron Bertrand Sep 04 '11 at 16:38
  • 2
    Again you'll have issues with scope. You'll need a massive dynamic SQL statement to generate the table variable structure, then populate it, then use it, return it, what have you. That will all have to happen in the same dynamic SQL batch. – Aaron Bertrand Sep 04 '11 at 16:39

2 Answers2

8

So here is how you can build the DECLARE TABLE statement dynamically:

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';


SELECT @sql = @sql + ',
' + c.name + ' ' + t.name
 + CASE
  WHEN t.name LIKE '%char' OR t.name LIKE '%binary' THEN
   '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE
   CONVERT(VARCHAR(4), c.max_length/CASE WHEN t.name LIKE 'n%'
   THEN 2 ELSE 1 END) END + ')'
  WHEN t.name IN ('float') THEN
      '(' + CONVERT(VARCHAR(4), c.precision) + ')'
  WHEN t.name IN ('decimal', 'numeric') THEN
   '(' + CONVERT(VARCHAR(4), c.precision) + ','
   + CONVERT(VARCHAR(4), c.scale) + ')'
  ELSE ''
 END
 FROM sys.columns AS c
 INNER JOIN sys.types AS t
 ON c.system_type_id = t.system_type_id
 AND c.user_type_id = t.user_type_id
 WHERE c.[object_id] = OBJECT_ID('dbo.Employees')
 ORDER BY c.column_id;

SET @sql = 'DECLARE @people TABLE (' + STUFF(@sql, 1, 1, '') + '
);';

SELECT @sql;

But now what? You can't insert into it from outside the scope of dynamic SQL:

EXEC sp_executesql @sql;
INSERT @people(id, name) SELECT 1,'foo';

Yields this error:

Msg 1087, Level 15, State 2, ...
Must declare the table variable "@people".

Once again, a scoping issue - @people only exists in the dynamic SQL and ceases to exist as soon as it's finished. So while you could proceed and append to the @sql variable:

SET @sql = @sql + 'INSERT @people ...; SELECT id, name FROM @people;';

...this will get out of hand very quickly. And I still have no idea how your C# code can be aware of all the columns and data types involved, but it's too hard to write the SQL to do so... you know you can drag the columns node from Object Explorer onto a query window and it will produce a nice comma-separated list of column names for you, right?

Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
2

You can query the system tables in order to find the names and types of the columns that a table consists of. See this question and its answers.

You can then take this information and generate scripts that will create the table value types.

This will not help on the client side, however, as it will need to know about the types and values of the data returned.

Community
  • 1
  • 1
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • Oded it is not possible like in simple SQL we do like Create table myable as (select * from Emp where 1=2;) it will create table as per some other structue of table. – user576510 Sep 04 '11 at 16:39
  • 1
    @user576510 - I don't understand. Are you asking me something or telling me something here? – Oded Sep 04 '11 at 16:57