2011-09-20 22 views
42

我需要從使用#temp表切換到@table變量,以便我可以在函數中使用它。查找SQL臨時表的數據類型

我的查詢使用插入#TEMP(從多個表),象這樣:

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

是否有一個簡單的方法來找出列的數據類型在#temp表,這樣我可以創建與#temp具有相同列和數據類型的@table變量?

+1

@AaronBertrand是正確的,但來自@gotqn答案是優秀的沒有'temp'表。 –

回答

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

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

我喜歡第二個建議,但它沒有在文本中提供類型,所以在這裏它與數據類型結合在一起。 'SELECT cols.column_id,cols.name,ty.name,cols.max_length,cols.precision,cols.scale FROM tempdb.sys.columns的cols \t上cols.system_type_id = ty.system_type_id加入sys.types TY WHERE [object_id] = OBJECT_ID(N'tempdb ..#myTable');' – RobbZ

2

是的,臨時表的數據類型將是您選擇並插入其中的列的數據類型。因此,只需查看select語句並根據您選擇的列確定每種數據類型即可。

+1

謝謝 - 我意識到你可以這樣做,但它成爲一個痛苦,必須檢查多個列和表,特別是如果它是一個巨大的臨時表。 – woggles

+0

@woggles我明白了。在這種情況下,billinkc的「懶惰」方式更適合你。 – Icarus

+1

現在我只需要找到很好的懶惰的方式來編寫declare @ table語句:) – woggles

1

我會去懶惰路線和使用

use tempdb 
GO 
EXECUTE sp_help #temp 
6

你需要限定的sp_help過程從tempdb數據庫運行,以獲取有關散列細節表,因爲這是散列表實際存儲的地方。如果您嘗試從其他數據庫運行sp_help,則會出現該表不存在於該數據庫中的錯誤。

如果執行查詢時tempdb的外面,因爲我認爲這是,你可以運行以下命令:

exec tempdb..sp_help #temp 

一個這個程序的好處是它包含的列數據類型爲你的文字描述。這使得它很容易複製並粘貼到另一個查詢中,例如如果您嘗試使用臨時表的定義來創建表變量。

您可以在Syscolumns表中找到相同的信息,但它會爲您提供您必須映射的類型的數字標識符。使用sp_help會爲您節省一個步驟。

+1

非常感謝你的回答,因爲它實際上解釋了所做的事情以及原因。 –

3

你要做的是獲得有關你正在查詢的列的系統類型的信息。您可以使用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

+0

我收到錯誤「元數據無法確定,因爲語句'SELECT * FROM tempdb.dbo。#T'使用臨時表。」對於臨時表... – blobbles

+0

請查看以下關於限制的文章 - https://msdn.microsoft.com/en-us/library/ff878258.aspx - 請參閱「備註」部分。 – gotqn

5

接受的答案呢不提供數據類型。使用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

其他的答案會給你你需要的信息,但仍需要你的時候,你定義表變量輸入這一切了。

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

正是我今天想要的 – Todd

0

得到柱與NAME數據類型使用這個

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

或 要獲得唯一的列名使用此

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