如何从查询返回 SQL 数据类型?

我有一个 SQL 查询,它查询一个我不需要也不想理解的庞大数据库(比如,数百个视图/表,名称像 CMM-CPP-FAP-ADD 这样难以阅读)。此查询的结果需要存储在临时表中,以便为报表提供内容。

我需要创建暂存表,但是有数百个视图/表要深入挖掘以找到这里所表示的数据类型,我不得不考虑是否有更好的方法来构造这个表。

有人能告诉我如何使用 SQLServer2008工具来占卜 SQL2000数据库中的源数据类型吗?

作为一个一般的例子,我想知道从查询如下:

SELECT Auth_First_Name, Auth_Last_Name, Auth_Favorite_Number
FROM Authors

而不是实际的结果,我想知道的是:

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

我对约束不感兴趣,我只想知道数据类型。

338903 次浏览
select * from information_schema.columns

could get you started.

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

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.

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

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.

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.

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

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;

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;

sp_describe_first_result_set

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

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

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

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

select CAST(0 AS BIT) AS OK

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.