14

我们有一个 SQL 查询,它从数据库的许多表/视图中提取大量字段。我们需要将规范放在一起以与第 3 方集成,编译结果集的数据类型的最快方法是什么?

说明:

  • 涉及 25 个以上的表/视图,因此表级别的功能仍然很麻烦。
  • 目前所有工作都在 Microsoft SQL Server Management Studio 中完成。
4

8 回答 8

14

您可能会使用一些快速 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 *
INTO #T
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 中结果集视图架构的启发

于 2013-12-04T01:41:29.627 回答
7

您可以使用 SET FMTONLY ON 运行查询,但这可能无法帮助您轻松确定返回的数据类型,因为您仅在 Management Studio 中工作。如果是我,我想我会临时创建一个与存储过程具有相同主体的视图(您可能必须为任何参数声明变量)。然后,您可以使用已经讨论过的 INFORMATION_SCHEMA 查询查看视图返回的列。

于 2009-01-13T18:54:31.183 回答
2

如果您使用的是 SQL Server,则表中提供了来自各种表的元数据information_schema。例如,要获取表 Foo 的列元数据,请发出以下查询:

SELECT * FROM information_schema.columns WHERE table_name = 'Foo'
于 2009-01-13T18:20:22.407 回答
2

如果您使用的是 C#,则可以直接从 DataRow 对象中的字段访问它:

Type columnNameType = row["columnName"].GetType();
于 2009-01-13T18:25:51.397 回答
2

对于其他替代方案,您可以使用

sp_help  'Table_Name'

编辑:此外, sp_help 可用于任何对象(即它会指示存储过程输入和输出变量的返回类型)

于 2009-01-13T18:29:20.020 回答
1

这是一个,如果你可以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 等效项,但这还不错,并且可以保持片段简短。

手动转换这些类型已经够麻烦了,扩展脚本是值得的。不确定我的转换是否正确。

于 2015-05-05T15:33:47.937 回答
1

一般来说,对于现有的表或视图,您希望使用系统目录或INFORMATION_SCHEMA.COLUMNS,但如果它是一个任意查询,您正在查看它会有点困难。

我会使用sys.dm_exec_describe_first_result_set动态管理视图。通常,最大的痛苦是必须用单引号转义您的查询。

DECLARE @tsql nvarchar(max) = N'SELECT YourFields FROM YourQuery';

SELECT *
FROM sys.dm_exec_describe_first_result_set(@tsql, null, 0);

有关更多信息,请参阅文档

或者,您可以使用sp_describe_first_result_set存储过程并获得基本相同的结果。(动态管理视图很好,因为您可以更轻松地使用 WHERE 进行过滤或使用 ORDER BY 进行排序。)

DECLARE @tsql nvarchar(max) = N'SELECT YourFields FROM YourQuery';

EXEC sp_describe_first_result_set @tsql, null, 0;

再次,请参阅文档以获取更多信息。

于 2021-08-05T17:29:53.967 回答
0

请注意,结果集元数据与表元数据不同,因为 SQL 查询可以包含表达式,其数据类型可能与它们查询的表中的数据类型不同。

许多 SQL 查询接口为您提供了一些功能来检索有关结果集元数据(数据类型等)的信息。

您需要使用的特定 API 函数取决于您使用的语言和查询界面。你没有说这个。

例如,如果您使用 ODBC,该SQLDescribeCol()函数可以为您提供有关结果集元数据的信息。

于 2009-01-13T18:30:03.403 回答