2011-09-20 20 views
42

Necesito cambiar de usar una tabla #temp a una variable @table para poder usarlo en una función.Encontrar los tipos de datos de una tabla temporal SQL

Mi consulta utiliza insertar en #temp (de varias tablas), así:

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

¿Hay una manera fácil de averiguar los tipos de datos de las columnas en la tabla #temp para que pueda crear la variable @table con las mismas columnas y tipos de datos que #temp?

+1

@AaronBertrand es correcta, pero la respuesta de @gotqn es excelente para ninguno 'temp' tablas. –

Respuesta

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

o

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

Me gustó la segunda sugerencia, pero no proporcionó tipos en el texto, por lo que aquí se combina con los tipos de datos. cols.column_id'SELECT, cols.name, ty.name, cols.max_length, cols.precision, cols.scale DE tempdb.sys.columns cols \t unen sys.types ty en cols.system_type_id = ty.system_type_id DONDE [object_id] = OBJECT_ID (N'tempdb .. # myTable ');' – RobbZ

2

Sí, los tipos de datos de la tabla temporal serán los tipos de datos de las columnas que está seleccionando e insertando en ella. Así que solo mire la declaración de selección y determine cada tipo de datos según la columna que seleccione.

+1

Gracias - Me doy cuenta de que puede hacerlo de esta manera, pero se convierte en un dolor tener que verificar a través de múltiples columnas y tablas, especialmente si se trata de una gran tabla temporal. – woggles

+0

@woggles veo. El enfoque 'lazy' de billinkc te sienta mejor en ese caso. – Icarus

+1

ahora solo necesito encontrar una buena forma de escribir la instrucción declare @ table :) – woggles

1

me gustaría ir la ruta perezoso y uso

use tempdb 
GO 
EXECUTE sp_help #temp 
6

que necesita para calificar el proceso sp_help para ejecutar desde la base de datos tempdb para obtener detalles acerca de un hash tabla, porque ahí es donde realmente se almacena la tabla hash. Si intenta ejecutar sp_help desde una base de datos diferente, obtendrá un error de que la tabla no existe en esa base de datos.

Si la consulta se ejecuta fuera de tempdb, como supongo que es, puede ejecutar el siguiente:

exec tempdb..sp_help #temp 

Una ventaja de este procedimiento es que incluye una descripción textual de los tipos de datos de columna para ti. Esto hace que sea muy fácil copiar y pegar en otra consulta, p. si intentas usar la definición de una tabla temporal para crear una variable de tabla.

Puede encontrar la misma información en la tabla Syscolumns, pero le dará identificadores numéricos para los tipos que tendrá que mapear usted mismo. El uso de sp_help te ahorrará un paso.

+1

Gracias por esto, mucho mejor que la respuesta aceptada porque realmente explica lo que se está haciendo y por qué. –

3

Lo que intenta hacer es obtener información sobre los tipos de sistema de las columnas que está consultando.

Para SQL Server 2012 and later puede usar la función sys.dm_exec_describe_first_result_set. Se devuelve información detallada acerca de las columnas y el system_type_column contiene la definición completa tipo de sistema (listo para usar en su definición de la tabla):

Por ejemplo:

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

Aparece el error "No se pudieron determinar los metadatos porque la instrucción 'SELECT * FROM tempdb.dbo. # T' usa una tabla temporal." para tablas temporales ... – blobbles

+0

Consulte el siguiente artículo sobre las limitaciones: https://msdn.microsoft.com/en-us/library/ff878258.aspx: consulte la sección 'Comentarios'. – gotqn

5

La respuesta aceptada hace no da el tipo de datos. Al asociar tempdb.sys.columns con sys.types, se obtiene el tipo de datos como se menciona en el comentario de la respuesta. Sin embargo, unir en system_type_id produce una fila adicional con el tipo de datos "sysname". En cambio, "user_type_id" da la solución exacta como se indica a continuación.

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

Las otras respuestas le darán la información que necesita, pero todavía requieren que escriba todo hacia fuera cuando se define la variable de tabla.

El siguiente TSQL le permitirá generar rápidamente la definición de la variable de tabla para cualquier tabla dada.

Esto le puede ahorrar mucho tiempo en lugar de escribir manualmente las definiciones de mesa como:

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 

Salida:

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

Exactamente lo que estaba buscando hoy – Todd

0

para obtener columnas nombrar con tipo de datos use este

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

o para obtener sólo por nombrar columnas para utilizar este

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