在编写查询时,有没有一种快速查看现有列大小的方法?

Is there a quick way to view the size of an existing column when writing a query?

我正在将一些 SSRS 报告中的大量嵌入式 SQL 转移到函数中。该过程通常涉及获取当前 select 查询、添加 INSERT INTO 部分并返回结果 table。像这样:

CREATE FUNCTION [dbo].[MyReportFunction]
(
    @userid        varchar(255),
    @location      varchar(255),
    more params here...
)

RETURNS @Results TABLE
(
    Title        nvarchar(max),
    Location     nvarchar(255),
    more columns here...
)
AS
BEGIN
    INSERT INTO @Results (Title, Location, more columns...)
    SELECT tblA.Title, tblB.Location, more columns...
    FROM TableA tblA
    INNER JOIN TableB tblB
    ON tblA.Id = tblB.Id
    WHERE tblB.Location = @location

    RETURN

END

作为其中的一部分,我必须将列放入@Results table 并根据从 SELECT 查询返回的内容为它们提供正确的大小和类型。现在获取类型很好,因为我可以将现有的 SELECT 查询复制并粘贴到一个新查询中,然后将鼠标悬停在列名上以获取它,例如列标题(nvarchar,空)。但是,我还需要知道大小。有没有一种简单的方法可以做到这一点而不必转到特定的 tables 并查看列列表?是否有一种方法可以编辑工具提示及其在鼠标悬停时显示的信息?

如果我有很多连接到不同的 tables 和一长串 tables 滚动浏览这可能会让人厌烦。

我正在使用 SQL Server 2008 R2

您可以简单地查询 INFORMATION_SCHEMA.COLUMNS 视图:

SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME IN('TableA', 'TableB')
AND COALESCE(CHARACTER_MAXIMUM_LENGTH, -1) > 0 

我通过将 CHARACTER_MAXIMUM_LENGTH 上的条件添加到结果集来进一步过滤结果。
这将只为您提供具有最大长度的列(varchar、char、nvarchar 等)。
我希望这对您有所帮助。

使用SQL_VARIANT_PROPERTY:

SELECT top 1
    SQL_VARIANT_PROPERTY(colname, 'BaseType') BaseType, 
    SQL_VARIANT_PROPERTY(colname, 'Precision') [Precision], 
    SQL_VARIANT_PROPERTY(colname, 'Scale') Scale, 
    SQL_VARIANT_PROPERTY(colname, 'MaxLength') [MaxLength]
FROM yourtable

结果可能是:

BaseType  Precision  Scale  MaxLength
int       10         0      4

作为 Zohar suggests, you can use INFORMATION_SCHEMA.COLUMNS,然后让查询引擎为您完成繁重的工作

SELECT TOP 0 * INTO #Temp FROM ( OriginalQuery ) o
SELECT column_name+' ' + 
        data_type + 
        case data_type
            when 'sql_variant' then ''
            when 'text' then ''
            when 'ntext' then ''
            when 'xml' then ''
            when 'decimal' then '(' + cast(numeric_precision as varchar) + ', ' + cast(numeric_scale as varchar) + ')'
            else coalesce('('+case when character_maximum_length = -1 then 'MAX' else cast(character_maximum_length as varchar) end +')','') 
        end +
        case when exists ( 
            select id from syscolumns
            where object_name(id)=TABLE_NAME
            and name=column_name
            and columnproperty(id,name,'IsIdentity') = 1 
            ) then
            ' IDENTITY(' + 
            cast(ident_seed(TABLE_NAME) as varchar) + ',' + 
            cast(ident_incr(TABLE_NAME) as varchar) + ')'
            else ''
        end + 
         (case when IS_NULLABLE = 'No' then ' NOT ' else ' ' end ) + 'NULL' + 
          case when tempdb.INFORMATION_SCHEMA.COLUMNS.COLUMN_DEFAULT IS NOT NULL THEN ' DEFAULT '+ tempdb.information_schema.columns.COLUMN_DEFAULT ELSE '' END + ',' 
FROM tempdb.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE '#Temp%'
DROP TABLE #TEMP

由于您的函数似乎只包含 INSERT ... SELECTRETURN,您可以将其更改为内联 TVF。这并不能真正回答您提出的问题,但它可能会解决首先需要知道确切数据类型的潜在问题:

DROP FUNCTION [dbo].[MyReportFunction]
-- multi-statement TVF and inline TVF are different object types,
-- so ALTER will not work, you have to drop and re-create the object
GO

CREATE FUNCTION [dbo].[MyReportFunction]
(
    @userid        varchar(255),
    @location      varchar(255),
    more params here...
)

<b>RETURNS TABLE</b>
AS
<b>RETURN
(</b>
    SELECT tblA.Title, tblB.Location, more columns...
    FROM TableA tblA
    INNER JOIN TableB tblB
    ON tblA.Id = tblB.Id
    WHERE tblB.Location = @location
<b>)</b>

您不仅不会因为这个开关而担心显式数据类型声明,您还会获得一个对查询优化器更透明的函数。如果使用该函数的查询很复杂,而不仅仅是 SELECT * FROM dbo.MyReportFunction(...),优化器将能够将函数的查询与主查询混合以获得更好的执行计划。