it-swarm.cn

查找SQL临时表的数据类型

我需要从使用#temp表切换到@table变量,以便我可以在函数中使用它。

我的查询使用insert到#temp(来自多个表),如下所示:

SELECT 
  a.col1, 
  a.col2, 
  b.col1... 
INTO #temp
FROM ...

有没有一种简单的方法可以找到#temp表中列的数据类型,这样我就可以使用与#temp相同的列和数据类型创建@table变量?

53
woggles
EXEC tempdb.dbo.sp_help N'#temp';

要么

SELECT [column] = c.name, 
       [type] = t.name, c.max_length, c.precision, c.scale, c.is_nullable 
    FROM tempdb.sys.columns AS c
    INNER JOIN sys.types AS t
    ON c.system_type_id = t.system_type_id
    AND t.system_type_id = t.user_type_id
    WHERE [object_id] = OBJECT_ID(N'tempdb..#temp');

这不适合你处理好事,比如调整varchar的max_length与nvarchar不同,但这是一个好的开始。

在SQL Server 2012或更高版本中,您可以使用新的DMF来描述结果集,该结果集可以解决该问题(并且还可以为您组装max_length/precision/scale)。但它不支持#temp表,所以只需注入查询 没有INTO

SELECT name, system_type_name, is_nullable
  FROM sys.dm_exec_describe_first_result_set(N'SELECT 
        a.col1, 
        a.col2, 
        b.col1... 
      --INTO #temp
      FROM ...;',NULL,1);
111
Aaron Bertrand

接受的答案没有给出数据类型。使用sys.types加入tempdb.sys.columns会给出答案注释中提到的数据类型。但是加入system_type_id会产生一个数据类型为“sysname”的额外行。相反,“user_type_id”给出了下面给出的确切解决方案。

SELECT cols.NAME
 ,ty.NAME
FROM tempdb.sys.columns cols
JOIN sys.types ty ON cols.user_type_id = ty.user_type_id
WHERE object_id = OBJECT_ID('tempdb..#temp')
9
bill

您需要限定sp_help进程以从tempdb数据库运行以获取有关哈希表的详细信息,因为这是哈希表实际存储的位置。如果您尝试从其他数据库运行sp_help,则会收到该数据库中不存在该表的错误。

如果您的查询在tempdb之外执行,正如我所假设的那样,您可以运行以下命令:

exec tempdb..sp_help #temp

此过程的一个好处是它包含列数据类型的文本说明。这使得复制和粘贴到另一个查询中非常容易,例如如果您正在尝试使用临时表的定义来创建表变量。

您可以在Syscolumns表中找到相同的信息,但它会为您自己映射的类型提供数字标识符。使用sp_help将为您节省一个步骤。

7
FistOfFury

其他答案将为您提供所需的信息,但仍需要您在定义表变量时全部输入。

以下TSQL将允许您快速生成任何给定表的表变量定义。

这可以为您节省大量时间,而不是手动输入表定义,如:

table(Field1Name nvarchar(4), Field2Name nvarchar(20), Field3Name int
, Field4Name numeric(28,12))

TSQL:

select top 10 * 
into #temp
from db.dbo.myTable



declare @tableName nvarchar(max)
set @tableName = '#temp'

use tempdb
declare @tmp table(val nvarchar(max))
insert into @tmp 
select case data_type   
    when 'binary' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
    when 'char' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
    when 'datetime2' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + CAST(DATETIME_PRECISION as nvarchar(max)) + ')'
    when 'datetimeoffset' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + CAST(DATETIME_PRECISION as nvarchar(max)) + ')'
    when 'decimal' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(NUMERIC_PRECISION as nvarchar(max)) + ',' + cast(NUMERIC_SCALE as nvarchar(max)) + ')'
    when 'nchar' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
    when 'numeric' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(NUMERIC_PRECISION as nvarchar(max)) + ',' + cast(NUMERIC_SCALE as nvarchar(max)) + ')'
    when 'nvarchar' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
    when 'time' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + CAST(DATETIME_PRECISION as nvarchar(max)) + ')'
    when 'varbinary' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
    when 'varchar' then COLUMN_NAME + ' ' + DATA_TYPE + '(' + cast(CHARACTER_MAXIMUM_LENGTH AS nvarchar(max)) + ')'
    -- Most standard data types follow the pattern in the other section.  
    -- Non-standard datatypes include: binary, char, datetime2, datetimeoffset, decimal, nvchar, numeric, nvarchar, time, varbinary, and varchar
    else COLUMN_NAME + ' ' + DATA_TYPE

    end +  case when IS_NULLABLE <> 'YES' then ' NOT NULL' else '' end 'dataType'
     from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME like @tableName + '%'

declare @result nvarchar(max)
set @result = ''
select @result = @result + [val] + N','
from @tmp
where val is not null

set @result = substring(@result, 1, (LEN(@result)-1))

-- The following will replce '-1' with 'max' in order to properly handle nvarchar(max) columns
set @result = REPLACE(@result, '-1', 'max')
select @result

输出:

Field1Name nvarchar(4), Field2Name nvarchar(20), Field3Name int
, Field4Name numeric(28,12)
3
Nick Painter

您要做的是获取有关要查询的列的系统类型的信息。

对于SQL Server 2012 and later,您可以使用 sys.dm_exec_describe_first_result_set function。它返回有关列的非常详细的信息,system_type_column包含完整的系统类型定义(准备在表定义中使用):

例如:

SELECT * 
FROM [sys].[dm_exec_describe_first_result_set] (N'SELECT object_id, name, type_desc FROM sys.indexes', null, 0);

enter image description here 

3
gotqn

获取具有数据类型的列名称使用此选项

EXEC tempdb.dbo.sp_help N'#temp';

或者只获取列名称以使用它

SELECT * 
FROM tempdb.sys.columns 
WHERE [object_id] = OBJECT_ID(N'tempdb..#temp');
2
Mohammad Shehroz

是的,临时表的数据类型将是您选择并插入其中的列的数据类型。因此,只需查看select语句,并根据您选择的列确定每种数据类型。

2
Icarus

我会去懒惰的路线并使用

use tempdb
GO
EXECUTE sp_help #temp
1
billinkc