How do I return the SQL data types from my query?

SqlSql ServerTsqlSql Server-2008

Sql Problem Overview


I've a SQL query that queries an enormous (as in, hundreds of views/tables with hard-to-read names like CMM-CPP-FAP-ADD) database that I don't need nor want to understand. The result of this query needs to be stored in a staging table to feed a report.

I need to create the staging table, but with hundreds of views/tables to dig through to find the data types that are being represented here, I have to wonder if there's a better way to construct this table.

Can anyone advise how I would use any of the SQL Server 2008 tools to divine the source data types in my SQL 2000 database?

As a general example, I want to know from a query like:

SELECT Auth_First_Name, Auth_Last_Name, Auth_Favorite_Number 
FROM Authors

Instead of the actual results, I want to know that:

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

I'm not interested in constraints, I really just want to know the data types.

Sql Solutions


Solution 1 - Sql

select * from information_schema.columns

could get you started.

Solution 2 - Sql

For SQL Server 2012 and above: If you place the query into a string then you can get the result set data types like so:

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

Solution 3 - Sql

You could also insert the results (or top 10 results) into a temp table and get the columns from the temp table (as long as the column names are all different).

SELECT TOP 10 *
INTO #TempTable
FROM <DataSource>

Then use:

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

or

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

Extrapolated from Aaron's answer here.

Solution 4 - Sql

You can also use...

SQL_VARIANT_PROPERTY()

...in cases where you don't have direct access to the metadata (e.g. a linked server query perhaps?).

In SQL Server 2005 and beyond you are better off using the catalog views (sys.columns) as opposed to INFORMATION_SCHEMA. Unless portability to other platforms is important. Just keep in mind that the INFORMATION_SCHEMA views won't change and so they will progressively be lacking information on new features etc. in successive versions of SQL Server.

Solution 5 - Sql

There MUST be en easier way to do this... Low and behold, there is...!

"sp_describe_first_result_set" is your friend!

Now I do realise the question was asked specifically for SQL Server 2000, but I was looking for a similar solution for later versions and discovered some native support in SQL to achieve this.

In SQL Server 2012 onwards cf. "sp_describe_first_result_set" - Link to BOL

I had already implemented a solution using a technique similar to @Trisped's above and ripped it out to implement the native SQL Server implementation.

In case you're not on SQL Server 2012 or Azure SQL Database yet, here's the stored proc I created for pre-2012 era databases:

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

Solution 6 - Sql

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

You can use columns aliases for better looking output.

Solution 7 - Sql

Can you get away with recreating the staging table from scratch every time the query is executed? If so you could use SELECT ... INTO syntax and let SQL Server worry about creating the table using the correct column types etc.

SELECT *
INTO your_staging_table
FROM enormous_collection_of_views_tables_etc

Solution 8 - Sql

This will give you everything column property related.

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;

Solution 9 - Sql

> sp_describe_first_result_set

will help to identify the datatypes of query by analyzing datatypes of first resultset of query

https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-describe-first-result-set-transact-sql?view=sql-server-2017

Solution 10 - Sql

I use a simple case statement to render results I can use in technical specification documents. This example does not contain every condition you will run into with a database, but it gives you a good template to work with.

SELECT
     TABLE_NAME          AS 'Table Name',
     COLUMN_NAME         AS 'Column Name',
     CASE WHEN DATA_TYPE LIKE '%char'
          THEN DATA_TYPE + '(' + CONVERT(VARCHAR, CHARACTER_MAXIMUM_LENGTH) + ')'
          WHEN DATA_TYPE IN ('bit', 'int', 'smallint', 'date')
          THEN DATA_TYPE
          WHEN DATA_TYPE = 'datetime'
          THEN DATA_TYPE + '(' + CONVERT(VARCHAR, DATETIME_PRECISION) + ')'
          WHEN DATA_TYPE = 'float'
          THEN DATA_TYPE
          WHEN DATA_TYPE IN ('numeric', 'money')
          THEN DATA_TYPE + '(' + CONVERT(VARCHAR, NUMERIC_PRECISION) + ', ' + CONVERT(VARCHAR, NUMERIC_PRECISION_RADIX) + ')'
     END                 AS 'Data Type',
     CASE WHEN IS_NULLABLE = 'NO'
          THEN 'NOT NULL'
          ELSE 'NULL'
     END                 AS 'PK/LK/NOT NULL'
FROM INFORMATION_SCHEMA.COLUMNS 
ORDER BY 
     TABLE_NAME, ORDINAL_POSITION

Solution 11 - Sql

Checking data types. The first way to check data types for SQL Server database is a query with the SYS schema table. The below query uses COLUMNS and TYPES tables:

    SELECT C.NAME AS COLUMN_NAME,
       TYPE_NAME(C.USER_TYPE_ID) AS DATA_TYPE,
       C.IS_NULLABLE,
       C.MAX_LENGTH,
       C.PRECISION,
       C.SCALE
FROM SYS.COLUMNS C
JOIN SYS.TYPES T
     ON C.USER_TYPE_ID=T.USER_TYPE_ID
WHERE C.OBJECT_ID=OBJECT_ID('your_table_name');

In this way, you can find data types of columns.

Solution 12 - Sql

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

Solution 13 - Sql

This easy query return a data type bit. You can use this thecnic for other data types:

select CAST(0 AS BIT) AS OK

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJMPView Question on Stackoverflow
Solution 1 - SqlerikkallenView Answer on Stackoverflow
Solution 2 - SqlredcalxView Answer on Stackoverflow
Solution 3 - SqlTrispedView Answer on Stackoverflow
Solution 4 - SqlAaron BertrandView Answer on Stackoverflow
Solution 5 - SqlPaul M SorauerView Answer on Stackoverflow
Solution 6 - SqlPawel CzapskiView Answer on Stackoverflow
Solution 7 - SqlLukeHView Answer on Stackoverflow
Solution 8 - Sqluser2074102View Answer on Stackoverflow
Solution 9 - SqlAlias VargheseView Answer on Stackoverflow
Solution 10 - SqlrsidebotView Answer on Stackoverflow
Solution 11 - SqlAmankhani MohammadJavadView Answer on Stackoverflow
Solution 12 - SqlbopView Answer on Stackoverflow
Solution 13 - SqlR.AlonsoView Answer on Stackoverflow