查找SQL临时表的数据类型

时间:2011-09-20 14:32:57

标签: sql sql-server

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

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

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

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

9 个答案:

答案 0 :(得分:112)

您需要确保sp_help在表所在的同一数据库(tempdb)中运行。您可以通过直接为呼叫添加前缀来执行此操作:

EXEC tempdb.dbo.sp_help @objname = N'#temp';

或者通过为tempdb.sys.columns添加联接前缀:

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 tempdb.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.dbo.#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);

答案 1 :(得分:9)

接受的答案没有给出数据类型。使用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')

答案 2 :(得分:7)

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

如果您的查询在tempdb之外执行,我认为是,您可以运行以下命令:

exec tempdb..sp_help #temp

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

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

答案 3 :(得分:3)

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

对于SQL Server 2012 and later,您可以使用sys.dm_exec_describe_first_result_set功能。它返回有关列的非常详细的信息,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

答案 4 :(得分:3)

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

以下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)

答案 5 :(得分:2)

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

答案 6 :(得分:2)

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

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

或 要仅获取列名称以使用此

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

答案 7 :(得分:1)

我会去懒惰路线并使用

use tempdb
GO
EXECUTE sp_help #temp

答案 8 :(得分:1)

查找SQL临时表的数据类型

方法1 –使用SP_HELP

EXEC TempDB..SP_HELP #TempTable;

enter image description here

注意-

在表格结构中,表格名称显示类似于“ #TempTable ________________________________________________________________________________________________________________________ 0000000004CB”。实际上,每个临时表名称的总长度为128。为了在多个会话中以不同的方式处理同一个临时表名称,SQL Server将在之间和字母数字末尾自动添加一些下划线。

方法2 –使用SP_COLUMNS

EXEC TempDB..SP_COLUMNS '#TempTable';

enter image description here

方法3 –使用系统表,例如INFORMATION_SCHEMA.COLUMNS,SYS.COLUMNS,SYS.TABLES

SELECT * FROM TempDB.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME IN (
SELECT NAME FROM TempDB.SYS.TABLES WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#TempTable')
);
GO

SELECT * FROM TempDB.SYS.COLUMNS WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#TempTable');
GO

SELECT * FROM TempDB.SYS.TABLES WHERE OBJECT_ID=OBJECT_ID('TempDB.dbo.#TempTable');
GO

enter image description here