在SQL Server存储过程中动态创建和选择表变量?

时间:2011-09-04 16:23:10

标签: sql sql-server tsql

请指导我如何动态创建表变量。我知道它可以是这样的:

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

如果不知道列和数据类型,我将如何创建。场景是我必须根据物理表和selct数据创建表变量,在SP中使用它们然后将表变量中的数据返回到C#程序。

例如,我有一个表Employees。我想创建一个与Employyes具有相同结构的表变量。但是提到列需要花费很多时间(因为员工大约有100列)

请建议。

2 个答案:

答案 0 :(得分:5)

以下是如何动态构建DECLARE TABLE语句:

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;

但现在呢?您无法从动态SQL范围之外插入其中:

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

产生此错误:

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

同样,范围问题 - @people仅存在于动态SQL中,并在完成后立即停止存在。因此,您可以继续并附加到@sql变量:

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

......这将很快失控。而且我仍然不知道你的C#代码如何知道所涉及的所有列和数据类型,但是编写SQL太难了...你知道你可以将列节点从对象资源管理器拖到查询中窗口,它会为你生成一个很好的以逗号分隔的列名列表,对吗?

答案 1 :(得分:1)

您可以查询系统表,以查找表所包含的列的名称和类型。请参阅此question及其答案。

然后,您可以获取此信息并生成将创建表值类型的脚本。

但是,这对客户端没有帮助,因为它需要知道返回数据的类型和值。