2009-01-13 11 views
8

Tenemos una consulta SQL que extrae una gran cantidad de campos de muchas tablas/vistas desde una base de datos. Necesitamos poner una especificación para la integración con un tercero, ¿cuál es la forma más rápida de compilar los tipos de datos del conjunto de resultados?¿Cómo se determinan los tipos de datos de los resultados de un SQL?

Aclaraciones:

  • Hay más de 25 tablas/vistas involucrados, por lo que funciona en el nivel de tabla seguirá siendo engorroso.
  • Todo el trabajo se está realizando actualmente en Microsoft SQL Server Management Studio.
+0

Esto depende en gran medida de qué idioma/plataforma se utiliza para recuperar esos valores. –

Respuesta

5

Puede ejecutar la consulta con SET FMTONLY ON, pero puede que no le ayude a determinar fácilmente los tipos de datos devueltos, ya que solo está trabajando en el estudio de administración. Si fuera yo, creo que crearía una vista temporalmente con el mismo cuerpo que el procedimiento almacenado (puede que tenga que declarar variables para cualquier parámetro). Luego puede ver las columnas devueltas por la vista con las consultas INFORMATION_SCHEMA ya discutidas.

+1

¡Crear la vista para usar las consultas NFORMATION_SCHEMA era el paso que faltaba! – Shawn

2

Si está utilizando SQL Server, los metadatos de varias tablas están disponibles en la tabla information_schema. Por ejemplo, para obtener metadatos de columna para la tabla de Foo, cuestión esta consulta:

SELECT * FROM information_schema.columns WHERE table_name = 'Foo' 
1

Si estaba utilizando C# que podría acceder a él desde el campo en el objeto DataRow:

Type columnNameType = row["columnName"].GetType(); 
2

Y para una alternativa adicional, puede usar

sp_help 'Table_Name' 

EDIT: Además, sp_help se puede utilizar para cualquier objeto (es decir, que indicaría el tipo de retorno de las variables de entrada y salida del procedimiento almacenado)

0

Tenga en cuenta que los metadatos del conjunto de resultados son diferentes de los metadatos de la tabla, porque las consultas SQL pueden incluir expresiones cuyos tipos de datos pueden no ser los mismos en las tablas que consultan.

Muchas interfaces de consulta SQL le dan alguna función para recuperar información sobre los metadatos del conjunto de resultados (tipos de datos, etc.).

Las funciones específicas de API que necesita utilizar dependen del idioma y la interfaz de consulta que está utilizando. No has declarado esto.

Por ejemplo, si usa ODBC, la función SQLDescribeCol() puede proporcionarle información sobre los metadatos del conjunto de resultados.

8

Puede usar algunas declaraciones rápidas de SQL para ver el tipo de columna de resultados, usando la tabla temporal.

Las tablas de temperatura son un poco mejor que una vista, ya que son ámbito de conexión local y se borrarán una vez desconectadas.

Todo lo que necesita es inyectar algunas palabras clave como seguimiento

SELECT 
TOP 0 -- to speed up without access data 
your,original,columns 
INTO #T -- temp table magic 
FROM originalTablesJoins 
Order by anything 
exec tempdb.sys.sp_columns #T 
drop table #T 

o;

SELECT TOP 0 * FROM (
    select your,original,columns from originalTablesJoins -- remove order by if any 
) x 
exec tempdb.sys.sp_columns #T 
drop table #T 

Nota: inspirado por View schema of resultset in SQL Server Management Studio

+0

Para la segunda opción que tuve que hacer: SELECCIONAR TOP 0 * EN #T FROM (... –

1

Aquí hay uno, si sólo puede SELECT ... INTO #Temp (recuerda #Temp se alcance la sesión en el peor) con un poco robado de https://stackoverflow.com/a/14328779/162273:

SELECT 
    c.name AS UsefulRawName, 
    ',' + c.name + ' ' + UPPER(t.name) + 
     CASE 
      WHEN t.name IN ('char', 'nchar', 'varchar', 'nvarchar') THEN '(' + CAST(c.max_length AS VARCHAR(3)) + ')' 
      WHEN t.name IN ('decimal', 'numeric') THEN '(' + CAST(c.[precision] AS VARCHAR(3)) + ', ' + CAST(c.[scale] AS VARCHAR(3)) + ')' 
      ELSE '' END + CASE WHEN c.Is_Nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END AS SQLColumnType, 
    'public ' + 
     CASE 
      WHEN t.name IN ('varchar', 'nvarchar', 'text', 'ntext', 'char', 'nchar', 'xml', 'sysname') THEN 'string' 
      WHEN t.name IN ('binary', 'varbinary', 'image') THEN 'byte[]' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('uniqueidentifier') THEN 'Guid' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('datetimeoffset') THEN 'DateTimeOffset' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('date', 'time', 'datetime2', 'smalldatetime', 'datetime') THEN 'DateTime' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('numeric', 'decimal', 'real', 'money', 'smallmoney') THEN 'decimal' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('float') THEN 'float' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('tinyint', 'smallint') THEN 'short' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('int') THEN 'int' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('bit') THEN 'bool' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('bigint') THEN 'long' + CASE WHEN c.Is_Nullable = 1 THEN '?' ELSE '' END 
      WHEN t.name IN ('timestamp') THEN 'ulong' 
      ELSE 'object' END + ' ' + c.name + ' { get; set; }' AS CSColumnType, 
    c.name + ' = ' + 
     CASE 
      WHEN t.name IN ('varchar', 'nvarchar', 'text', 'ntext', 'char', 'nchar', 'xml', 'sysname') THEN 'reader["' + c.name + '"] as string,' 
      WHEN t.name IN ('binary', 'varbinary', 'image') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as byte[]?,' 
                 ELSE '(byte[])reader["' + c.name + '"],' END 
      WHEN t.name IN ('uniqueidentifier') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as Guid?,' 
                 ELSE '(Guid)reader["' + c.name + '"],' END 
      WHEN t.name IN ('datetimeoffset') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as DateTimeOffset?,' 
                 ELSE '(DateTimeOffset)reader["' + c.name + '"],' END 
      WHEN t.name IN ('date', 'time', 'datetime2', 'smalldatetime', 'datetime') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as DateTime?,' 
                 ELSE '(DateTime)reader["' + c.name + '"],' END 
      WHEN t.name IN ('numeric', 'decimal', 'real', 'money', 'smallmoney') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as decimal?,' 
                 ELSE '(decimal)reader["' + c.name + '"],' END 
      WHEN t.name IN ('float') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as float?,' 
                 ELSE '(float)reader["' + c.name + '"],' END 
      WHEN t.name IN ('tinyint', 'smallint') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as short?,' 
                 ELSE '(short)reader["' + c.name + '"],' END 
      WHEN t.name IN ('int') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as int?,' 
                 ELSE '(int)reader["' + c.name + '"],' END 
      WHEN t.name IN ('bit') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as bool?,' 
                 ELSE '(bool)reader["' + c.name + '"],' END 
      WHEN t.name IN ('bigint') THEN CASE 
                 WHEN c.Is_Nullable = 1 THEN 'reader["' + c.name + '"] as long?,' 
                 ELSE '(long)reader["' + c.name + '"],' END 
      WHEN t.name IN ('timestamp') THEN '(ulong)reader["' + c.name + '"],' 
      ELSE 'reader["' + c.name + '"] == DBNull.Value ? null : reader["' + c.name + '"],' END AS ReaderStatements 
FROM tempDb.sys.columns c 
INNER JOIN 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('tempdb..#Temp') 
ORDER BY column_id 

Una persona más motivada podría hacer un mapeo más inteligente de los tipos a .Net equivalentes automáticamente, pero esto no es tan malo y mantiene el fragmento corto.

La conversión manual de estos tipos fue suficiente como para hacer que la escritura valiera la pena. No estoy seguro de que mis conversiones sean todas correctas.

Cuestiones relacionadas