2011-09-20 17 views
42

Devo passare dall'utilizzo di una tabella #temp a una variabile @table in modo che possa essere utilizzata in una funzione.Ricerca dei tipi di dati di una tabella temporanea SQL

mio query utilizza inserire nel #temp (da più tabelle) in questo modo:

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

C'è un modo semplice per scoprire i tipi di dati delle colonne della tabella #temp modo che io possa creare la variabile @table con le stesse colonne e tipi di dati di #temp?

+1

@AaronBertrand è giusto, ma la risposta da @gotqn è eccellente per nessuno 'temp' tabelle. –

risposta

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

o

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

Mi è piaciuto il secondo suggerimento ma non forniva i tipi nel testo, quindi qui è unito ai tipi di dati. 'SELECT cols.column_id, cols.name, ty.name, cols.max_length, cols.precision, cols.scale DA tempdb.sys.columns Cols \t unirsi sys.types ty su cols.system_type_id = ty.system_type_id DOVE [object_id] = OBJECT_ID (N'tempdb .. # myTable ');' – RobbZ

2

Sì, i tipi di dati della tabella temporanea saranno i tipi di dati delle colonne che si selezionano e si inseriscono in esso. Quindi basta guardare l'istruzione select e determinare ogni tipo di dati in base alla colonna selezionata.

+1

Grazie - Mi rendo conto che puoi farlo in questo modo ma diventa difficile dover controllare più colonne e tabelle, soprattutto se è un enorme tavolo temporaneo. – woggles

+0

@woggles che vedo. L'approccio 'pigro' di Billinkc ti si addice meglio in quel caso. – Icarus

+1

ora ho solo bisogno di trovare un bel modo pigro per codificare la dichiarazione di dichiarazione @ tabella :) – woggles

1

mi piacerebbe andare il percorso pigro e utilizzare

use tempdb 
GO 
EXECUTE sp_help #temp 
6

è necessario qualificare il processo sp_help a decorrere dal database tempdb per ottenere dettagli su un hash tabella, perché è lì che la tabella hash è effettivamente memorizzata. Se si tenta di eseguire sp_help da un database diverso, si otterrà un errore che la tabella non esiste in quel database.

Se la query è in esecuzione al di fuori di tempdb, come suppongo che sia, è possibile eseguire le seguenti operazioni:

exec tempdb..sp_help #temp 

Uno dei vantaggi di questa procedura è che include una descrizione dei tipi di dati di colonna per voi. Ciò semplifica la copia e l'incolla in un'altra query, ad es. se stai cercando di utilizzare la definizione di una tabella temporanea per creare una variabile di tabella.

È possibile trovare le stesse informazioni nella tabella Syscolumns, ma fornirà indentificatori numerici per i tipi che dovranno essere mappati. L'utilizzo di sp_help ti farà risparmiare un passo.

+1

Grazie per questo, molto meglio della risposta accettata perché in realtà spiega cosa si sta facendo e perché. –

3

Quello che stai cercando di fare è ottenere informazioni sui tipi di sistema delle colonne che stai interrogando.

Per SQL Server 2012 and later è possibile utilizzare la funzione sys.dm_exec_describe_first_result_set. Esso restituisce informazioni molto dettagliate sulle colonne e la system_type_column detiene la definizione completa tipo di sistema (pronto per l'uso nella vostra definizione di tabella):

Ad esempio:

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

Viene visualizzato l'errore "Impossibile determinare i metadati perché l'istruzione 'SELECT * FROM tempdb.dbo. # T' utilizza una tabella temporanea." per le tabelle temporanee ... – blobbles

+0

Controllare il seguente articolo sulle limitazioni - https://msdn.microsoft.com/en-us/library/ff878258.aspx - consultare la sezione "Note". – gotqn

5

La risposta accettata fa non dare il tipo di dati. L'aggiornamento di tempdb.sys.columns con sys.types fornisce il tipo di dati come menzionato nel commento della risposta. Ma l'adesione a system_type_id produce una riga aggiuntiva con tipo di dati "sysname". Invece "user_type_id" fornisce la soluzione esatta come indicato di seguito.

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

Le altre risposte ti daranno le informazioni che ti servono, ma ti chiedono comunque di scriverle tutte quando definisci la variabile di tabella.

Il seguente TSQL consentirà di generare rapidamente la definizione della variabile di tabella per qualsiasi tabella specificata.

Questo può risparmiare un sacco di tempo invece di digitare manualmente le definizioni da tavolo come:

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 

uscita:

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

Esattamente quello che stavo cercando oggi – Todd

0

per ottenere le colonne di nome con tipo di dati usa questo

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

o Per ottenere solo le colonne nome da utilizzare questo

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