How to determine the datatypes of the results of a SQL?

让人想犯罪 __ 提交于 2019-11-28 00:13:19

问题


We have a SQL query that pulls a large number of fields from many tables/views from a database. We need to put a spec together for integration with a 3rd party, what is the quickest way to compile the data types of the result set?

Clarifications:

  • There are 25+ tables/views involved, so functions at the table level will still be cumbersome.
  • All work is currently being done in Microsoft SQL Server Management Studio.

回答1:


You can run the query with SET FMTONLY ON, but that might not help you to easily determine the data types returned, since you're working in management studio only. If it was me, I think I'd create a view temporarily with the same body as the stored procedure (you may have to declare variables for any parameters). You can then look at the columns returned by the view with the INFORMATION_SCHEMA queries already discussed.




回答2:


You might use few quick SQL statements to view result column type, by using temp table.

Temp tables is a little better then a view, as they are connection-local scope and will be cleared once disconnect.

All you need is inject few keyword as follow

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

or;

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

Note: inspired by View schema of resultset in SQL Server Management Studio




回答3:


If you're using SQL Server, metadata from various tables is available in the information_schema table. For instance, to get column metadata for table Foo, issue this query:

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



回答4:


If you were using C# you could access it right from the field in the DataRow object:

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



回答5:


And for an additional alternative you can use

sp_help  'Table_Name'

EDIT: Also, sp_help can be used for any object ( i.e. it would indicate the return type of stored procedure input and output variables)




回答6:


Here's one, if you can just SELECT ... INTO #Temp (remember #Temp is scoped to the session at worst) with some stolen from 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

A more motivated person could do some smarter mapping of the types to .Net equivalents automatically but this isn't so bad and keeps the snippet short.

Converting these types manually was enough of a pain in the butt that extending the script was worthwhile. Not sure my conversions are all correct.




回答7:


Note that result set metadata is different from table metadata, because SQL queries can include expressions, whose data types may not be the same as those in the tables they query.

Many SQL query interfaces give you some function to retrieve information about the result set metadata (datatypes, etc.).

The specific API functions you need to use depend on what language and query interface you're using. You haven't stated this.

For instance, if you're using ODBC, the SQLDescribeCol() function can give you information about the result set metadata.



来源:https://stackoverflow.com/questions/440123/how-to-determine-the-datatypes-of-the-results-of-a-sql

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!