2009-10-21 8 views
42

Tengo una consulta SQL que consulta una base de datos enorme (como, cientos de visitas/tablas con nombres difíciles de leer como CMM-CPP-FAP-ADD) que no necesito ni quiero entender. El resultado de esta consulta debe almacenarse en una tabla de etapas para alimentar un informe.¿Cómo devuelvo los tipos de datos SQL de mi consulta?

Necesito crear la tabla de etapas, pero con cientos de vistas/tablas para encontrar los tipos de datos que están siendo representados aquí, me pregunto si hay una mejor manera de construir esta tabla.

¿Alguien puede aconsejar cómo usaría cualquiera de las herramientas de SQL Server 2008 para adivinar los tipos de datos fuente en mi base de datos SQL 2000?

Como ejemplo general, quiero saber de una consulta como:

SELECT Auth_First_Name, Auth_Last_Name, Auth_Favorite_Number 
FROM Authors 

En lugar de los resultados reales, quiero saber que:

Auth_First_Name is char(25) 
Auth_Last_Name is char(50) 
Auth_Favorite_Number is int 

No estoy interesado en limitaciones, realmente solo quiero saber los tipos de datos.

Respuesta

46
select * from information_schema.columns 

podría comenzar.

+0

nombre de objeto no válido '' INFORMATION_SCHEMA.COLUMNS – JMP

+3

Do usted tiene una base de datos SENSIBLE AL CASO? Si es así, debe usar 'SELECT * FROM INFORMATION_SCHEMA.Columns' –

+1

Sí, es sensible a mayúsculas y minúsculas. Intenté SELECT * FROM INFORMATION_SCHEMA.Columns y obtuve el mismo error de objeto no válido. Este es SQL Server 2000 (8.0.2055), ¿INFORMATION_SCHEMA existe en esta versión? – JMP

5

¿Se puede salir con la recreación de la tabla de etapas desde cero cada vez que se ejecuta la consulta? Si es así usted podría utilizar SELECT ... INTO sintaxis y dejar que la preocupación de SQL Server sobre la creación de la tabla utilizando el tipo correcto de columnas etc.

SELECT * 
INTO your_staging_table 
FROM enormous_collection_of_views_tables_etc 
+0

Desafortunadamente no es una opción. – JMP

+0

También pudo crear esa tabla de etapas solo para obtener los tipos de datos de columnas, utilizando la tabla information_schema señalada por erikkallen. – Spidey

+5

@JM: ¿Qué le parece si ejecuta la sintaxis 'SELECT ... INTO ... FROM ... WHERE 1 = 0' como una opción única para crear una tabla ficticia, y luego utiliza Management Studio para ejecutar el SQL de creación de tabla para la mesa ficticia? – LukeH

16

También puede utilizar ...

SQL_VARIANT_PROPERTY() 

... en los casos en usted no tiene acceso directo a los metadatos (por ejemplo, ¿quizás una consulta del servidor vinculado?).

http://msdn.microsoft.com/en-us/library/ms178550.aspx

En SQL Server 2005 y más allá de que es mejor usar las vistas de catálogo (sys.columns) en comparación con INFORMATION_SCHEMA. A menos que la portabilidad a otras plataformas sea importante. Solo tenga en cuenta que las vistas de INFORMATION_SCHEMA no cambiarán y que progresivamente carecerán de información sobre las nuevas funciones, etc. en las sucesivas versiones de SQL Server.

+0

Esto no funcionará para campos de texto. Lanzaremos esta excepción: "Choque de tipo operando: el texto es incompatible con sql_variant" – eflles

+1

@eflles Gracias, recuerden que este es un caso excepcional (cuando no tienen acceso a los metadatos) y, incluso en 2009 cuando surgió esta pregunta, deberías haber abandonado 'text',' ntext', y 'image'. Si la gente todavía usa esos hoy, esto es solo una pequeña parte de sus problemas ... –

0
select COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH 
from INFORMATION_SCHEMA.COLUMNS 
where TABLE_NAME='yourTable'; 
18

También puede insertar los resultados (o los 10 mejores resultados) en una tabla temporal y obtener las columnas de la tabla temporal (siempre y cuando los nombres de columna son todos diferentes).

SELECT TOP 10 * 
INTO #TempTable 
FROM <DataSource> 

A continuación, utilice:

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

o

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

extrapolada a partir de Aaron's answer here.

5
SELECT COLUMN_NAME, 
     DATA_TYPE, 
     CHARACTER_MAXIMUM_LENGTH 
FROM information_schema.columns 
WHERE TABLE_NAME = 'YOUR_TABLE_NAME' 

Puede usar alias de columnas para obtener una mejor apariencia.

8

There DEBE ser en una manera más fácil de hacer esto ... ¡Bajo y he aquí, hay ...!

"sp_describe_first_result_set" es tu amigo!

Ahora me doy cuenta de que la pregunta fue hecha específicamente para SQL Server 2000, pero estaba buscando una solución similar para versiones posteriores y descubrí compatibilidad nativa en SQL para lograr esto.

En SQL Server 2012 en adelante cf. "sp_describe_first_result_set" - Link to BOL

Ya había implementado una solución usando una técnica similar a @Trisped's anterior y la arranqué para implementar la implementación nativa de SQL Server.

En caso de que no estás en SQL Server 2012 o de base de datos SQL Azure sin embargo, aquí está el procedimiento almacenado que creé para las bases de datos de la era pre-2012:

CREATE PROCEDURE [fn].[GetQueryResultMetadata] 
    @queryText VARCHAR(MAX) 
AS 
BEGIN 

    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    --SET NOCOUNT ON; 

    PRINT @queryText; 

    DECLARE 
       @sqlToExec NVARCHAR(MAX) = 
        'SELECT TOP 1 * INTO #QueryMetadata FROM (' 
        + 
        @queryText 
        + 
        ') T;' 
        + ' 
         SELECT 
            C.Name       [ColumnName], 
            TP.Name       [ColumnType], 
            C.max_length     [MaxLength], 
            C.[precision]     [Precision], 
            C.[scale]      [Scale], 
            C.[is_nullable]     IsNullable 
         FROM 
            tempdb.sys.columns    C 
             INNER JOIN 
            tempdb.sys.types    TP 
                       ON 
                         TP.system_type_id = C.system_type_id 
                          AND 
                         -- exclude custom types 
                         TP.system_type_id = TP.user_type_id 
         WHERE 
            [object_id] = OBJECT_ID(N''tempdb..#QueryMetadata''); 
      ' 

    EXEC sp_executesql @sqlToExec 

END 
1

Esto le dará todo lo relacionado con propiedad de la columna.

SELECT * INTO TMP1 
FROM (SELECT TOP 1 /* rest of your query expression here */); 

SELECT o.name AS obj_name, TYPE_NAME(c.user_type_id) AS type_name, c.* 
FROM sys.objects AS o 
JOIN sys.columns AS c ON o.object_id = c.object_id 
WHERE o.name = 'TMP1'; 

DROP TABLE TMP1; 
2

Para SQL Server 2012 y superiores: Si se coloca la consulta en una cadena, entonces puede obtener los tipos de datos de conjunto de resultados, así:

DECLARE @query nvarchar(max) = 'select 12.1/10.1 AS [Column1]'; 
EXEC sp_describe_first_result_set @query, null, 0; 
Cuestiones relacionadas