Как определить типы данных результатов SQL? - PullRequest
10 голосов
/ 13 января 2009

У нас есть SQL-запрос, который извлекает большое количество полей из многих таблиц / представлений из базы данных. Нам нужно собрать спецификацию для интеграции со сторонней организацией. Какой самый быстрый способ компилировать типы данных результирующего набора?

Пояснения:

  • Здесь задействовано более 25 таблиц / представлений, поэтому функции на уровне таблиц по-прежнему будут громоздкими.
  • В настоящее время вся работа выполняется в Microsoft SQL Server Management Studio.

Ответы [ 7 ]

10 голосов
/ 04 декабря 2013

Вы можете использовать несколько быстрых операторов SQL для просмотра типа столбца результата, используя временную таблицу.

Временные таблицы немного лучше представления, поскольку они являются локальной областью подключения и будут очищены после отключения.

Все, что вам нужно, это ввести несколько ключевых слов, как следует

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

или;

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

Примечание: вдохновлено Просмотр схемы набора результатов в SQL Server Management Studio

6 голосов
/ 13 января 2009

Вы можете выполнить запрос с помощью SET FMTONLY ON, но это может не помочь вам легко определить возвращаемые типы данных, поскольку вы работаете только в Management Studio. Если бы это был я, я думаю, я бы временно создал представление с тем же телом, что и хранимая процедура (возможно, вам придется объявить переменные для любых параметров). Затем вы можете просмотреть столбцы, возвращаемые представлением, с уже обсужденными запросами INFORMATION_SCHEMA.

2 голосов
/ 13 января 2009

А для дополнительной альтернативы вы можете использовать

sp_help  'Table_Name'

РЕДАКТИРОВАНИЕ: Кроме того, sp_help может использоваться для любого объекта (т. Е. Он будет указывать тип возвращаемых переменных ввода и вывода хранимой процедуры)

2 голосов
/ 13 января 2009

Если вы используете C #, вы можете получить к нему доступ прямо из поля объекта DataRow:

Type columnNameType = row["columnName"].GetType();
2 голосов
/ 13 января 2009

Если вы используете SQL Server, метаданные из различных таблиц доступны в таблице information_schema. Например, чтобы получить метаданные столбца для таблицы Foo, введите следующий запрос:

SELECT * FROM information_schema.columns WHERE table_name = 'Foo'
1 голос
/ 05 мая 2015

Вот один из них, если вы можете просто SELECT ... INTO #Temp (помните, #Temp ограничено на сеанс в худшем случае) с некоторыми украденными из 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

Более мотивированный человек может автоматически сделать более умное сопоставление типов с .Net-эквивалентами, но это не так уж плохо и делает короткий фрагмент коротким.

Преобразование этих типов вручную было достаточно неприятно, так как расширение сценария того стоило. Не уверен, что все мои преобразования верны.

0 голосов
/ 13 января 2009

Обратите внимание, что метаданные набора результатов отличаются от метаданных таблицы, поскольку запросы SQL могут включать выражения, типы данных которых могут не совпадать с типами данных в запрашиваемых таблицах.

Многие интерфейсы SQL-запросов предоставляют некоторую функцию для получения информации о метаданных набора результатов (типы данных и т. Д.).

Конкретные функции API, которые вам нужно использовать, зависят от того, какой язык и интерфейс запроса вы используете. Вы не заявили об этом.

Например, если вы используете ODBC, функция SQLDescribeCol() может предоставить вам информацию о метаданных набора результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...