【问题标题】:Get data types from arbitrary sql statement in SQL Server 2008从 SQL Server 2008 中的任意 sql 语句获取数据类型
【发布时间】:2010-04-03 08:04:55
【问题描述】:

给定一些任意 SQL,我想获取返回列的数据类型。该语句可能会连接许多表、视图、TVF 等。我知道我可以根据查询创建一个视图并从中获取数据类型,希望有更快的方法。只觉得我能想到的是编写一个.net 实用程序来运行 SQL 并检查结果,想知道是否有 TSQL 答案。


即

给定(不是真实的表格只是一个例子)

SELECT p.Name AS PersonName, p.Age, a.Account as AccountName
FROM Person as p
LEFT JOIN Account as a
    ON p.Id = a.OwnerId

我想要类似的东西

PersonName: (nvarchar(255), not null)

年龄:(smallInt,不为空)

等等……

【问题讨论】:

  • @HLGEM 我需要在数据集市中创建一些表,以匹配源系统中某些查询的架构。

标签: sql sql-server tsql sql-server-2008


【解决方案1】:
    /*you may have to alias some columns if they are not unique*/
    /*EDIT: added fix for 2byte nchar/nvarchar */
    SELECT top (1)  /*<your query columns here>*/ 
    INTO #tmp99
    /*<rest of your query here>*/


    SELECT 'CREATE TABLE [tablename]('  UNION ALL 
    SELECT CASE WHEN ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) = 1 THEN '' ELSE ',' END 
    + CHAR(13) + '[' + c.name + '] [' + t.name + ']' 
    + CASE WHEN c.system_type_id IN (165,167,173,175) 
           THEN CASE WHEN c.max_length <> -1
                     THEN '(' + CAST(c.max_length AS varchar(7)) + ')' 
                     ELSE '(max)' 
                     END 
           WHEN c.system_type_id IN (231,239) 
           THEN CASE WHEN c.max_length <> -1 
                     THEN '(' + CAST(c.max_length/2 AS varchar(7)) + ')' 
                     ELSE '(max)' END
           ELSE 
               CASE WHEN c.system_type_id IN (41,42,43) 
                    THEN '(' + CAST(c.scale AS varchar(7)) + ')'
                    ELSE
                        CASE WHEN c.system_type_id IN (106,108) 
                             THEN '(' + CAST(c.precisiON AS varchar(7)) + ',' + CAST(c.scale AS varchar(7)) + ')'
                             ELSE ''
                             END 
                    END
           END

    + CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END 

    FROM tempdb.sys.columns c
    JOIN tempdb..sysobjects o ON (c.object_id = o.id)
    JOIN tempdb.sys.types t ON (t.user_type_id = c.user_type_id)
    WHERE o.name LIKE '#tmp99%' 
    UNION ALL SELECT ')' 
    FOR XML PATH('')

    DROP TABLE #tmp99

【讨论】:

  • 这很简洁,似乎运作良好。我注意到的唯一问题是双字节字段的长度不正确(即 nvarchar(255) 变为 nvarchar(510) ),所以我只是为 system_type_id IN (231,239) 添加了另一种情况,我将长度除以二。跨度>
  • 这个周末我会修好它。我很快就把它拼凑起来了,所以希望它至少能给你一个好的开始,你需要什么
  • 感谢 Scot,我刚刚添加了以下内容,并从第一个案例中删除了 231 和 239,所以它对我来说效果很好。 WHEN c.system_type_id IN (231,239) THEN CASE WHEN c.max_length -1 THEN '(' + CAST(c.max_length/2 AS varchar(7)) + ')' ELSE '(max)' END
【解决方案2】:

我试图实现这个目标,但它变得太难了。让我告诉我如何接近它。我使用了 SQL 解析器:http://www.sqlparser.com/download.php 和 C#。然后尝试分析文本。对于简单的查询,它是可以的,但很快它就会变得过于编译。关于视图的想法看起来要简单得多。

【讨论】:

    猜你喜欢
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    相关资源
    最近更新 更多