17

テーブルからすべての列のリストを、データ型、データ長、およびその列の最長値の長さとともに取得しようとしています。

列とそのデータ型および長さを取得するための次のSQLがあります。

SELECT 
    Object_Name(c.object_id),
    c.name 'Column Name',
    t.Name 'Data type',
    c.max_length 'Max Length'
FROM    
    sys.columns c
INNER JOIN 
    sys.types t ON c.system_type_id = t.system_type_id
WHERE
    c.object_id = OBJECT_ID('MyTable')

そして、値の最大長を取得するための次のSQLがあります。

SELECT Max(Len(MyColumn))
FROM MyTable

しかし、私はそれらを組み合わせる方法を理解することはできません。SQLServer2008を使用しています。

4

14 に答える 14

17

提案をありがとう。私は次の解決策を思いついた。必要なデータを取得できますが、より効率的にできるかどうかを確認したいと思います。

declare @results table
(
ID varchar(36),
TableName varchar(250),
ColumnName varchar(250),
DataType varchar(250),
MaxLength varchar(250),
Longest varchar(250),
SQLText varchar(250)
)

INSERT INTO @results(ID,TableName,ColumnName,DataType,MaxLength,Longest,SQLText)
SELECT 
    NEWID(),
    Object_Name(c.object_id),
    c.name,
    t.Name,
    case 
        when t.Name != 'varchar' Then 'NA'
        when c.max_length = -1 then 'Max' 
        else CAST(c.max_length as varchar)
    end,
    'NA',
    'SELECT Max(Len(' + c.name + ')) FROM ' + OBJECT_SCHEMA_NAME(c.object_id) + '.' + Object_Name(c.object_id)
FROM    
    sys.columns c
INNER JOIN 
    sys.types t ON c.system_type_id = t.system_type_id
WHERE
    c.object_id = OBJECT_ID('MyTable')    


DECLARE @id varchar(36)
DECLARE @sql varchar(200)
declare @receiver table(theCount int)

DECLARE length_cursor CURSOR
    FOR SELECT ID, SQLText FROM @results WHERE MaxLength != 'NA'
OPEN length_cursor
FETCH NEXT FROM length_cursor
INTO @id, @sql
WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO @receiver (theCount)
    exec(@sql)

    UPDATE @results
    SET Longest = (SELECT theCount FROM @receiver)
    WHERE ID = @id

    DELETE FROM @receiver

    FETCH NEXT FROM length_cursor
    INTO @id, @sql
END
CLOSE length_cursor
DEALLOCATE length_cursor


SELECT 
    TableName, 
    ColumnName, 
    DataType, 
    MaxLength, 
    Longest 
FROM 
    @results
于 2013-01-24T14:47:07.523 に答える
11

これは、役立つ可能性のあるデータのプロファイルを作成するために使用するものです。「YOURTABLENAME」を自分のテーブル名に変更するだけです。これは、列をトリミングできる場所を示すことを目的としています。

DECLARE @YourTableName sysname;
DECLARE @sql nvarchar(MAX) = ''
SET @YourTableName = YOUR TABLE NAME 
CREATE TABLE #resultsTable (columnName varchar(100), columnLargestValueInData int, columnMaxLength int)

DECLARE @whileIter int = 1
DECLARE @whileTotal int  

SELECT @whileTotal = COUNT(*) FROM sys.columns c
                            INNER JOIN 
                                sys.types t ON c.user_type_id = t.user_type_id
                            WHERE
                                c.object_id = OBJECT_ID(@YourTableName)
-- print 'whileTotal: ' + CONVERT(VARCHAR,@whileTotal) -- used for testing
WHILE @whileIter <= @whileTotal
BEGIN

SELECT  @sql =  N'INSERT INTO #resultsTable (columnName,  columnLargestValueInData, columnMaxLength) SELECT ''' + sc.name + ''' AS columnName, max(len([' + sc.name + '])), ' + CONVERT(varchar,sc.max_length) + ' FROM [' + t.name + ']'  
FROM  sys.tables AS t
INNER JOIN sys.columns AS sc ON t.object_id = sc.object_id
INNER JOIN sys.types AS st ON sc.system_type_id = st.system_type_id
WHERE column_id = @whileIter
AND t.name = @YourTableName
AND st.name IN ('char', 'varchar', 'nchar', 'nvarchar')

PRINT @sql

exec sp_executesql @sql
SET @whileIter += 1
END
SELECT * FROM #resultsTable

TRUNCATE TABLE #resultsTable
DROP TABLE #resultsTable
于 2014-06-20T21:13:13.433 に答える
7

これは私が何年も使ってきたバージョンです。スペースの代わりにアンダースコアを使用して、末尾のスペースで実際のデータ長を指定します。

set nocount on;
declare @TableName varchar(150) = 'TableName';
declare @Schema varchar(20) = 'TableSchema';
declare @Columns varchar(max);
declare @Unpivot varchar(max);
declare @SQL varchar(max);

select  @Columns = STUFF((
select  ',max(len(replace([' + COLUMN_NAME + '],'' '',''_'')))[' + COLUMN_NAME + '/' 
        + isnull(ltrim(CHARACTER_MAXIMUM_LENGTH),DATA_TYPE) + ']' + CHAR(10) + CHAR(9)
from    INFORMATION_SCHEMA.COLUMNS
where   TABLE_SCHEMA = @Schema
        and TABLE_NAME = @TableName
order   by ORDINAL_POSITION
for XML PATH('')),1,1,'')

select  @Unpivot = STUFF((
select  ',[' + COLUMN_NAME + '/' + isnull(ltrim(CHARACTER_MAXIMUM_LENGTH),DATA_TYPE) + ']'
from    INFORMATION_SCHEMA.COLUMNS
where   TABLE_SCHEMA = @Schema
        and TABLE_NAME = @TableName
order   by ORDINAL_POSITION
for XML PATH('')),1,1,'')

select  @SQL = 
'select DataSize, ColumnName [ColumnName/Size]
from    (
        select ' + @Columns + 'from [' + @Schema + '].[' + @TableName + ']
        )x 
unpivot (DataSize for ColumnName in (' + @Unpivot + '))p'

print (@SQL)
exec (@SQL)
于 2017-01-11T20:57:29.790 に答える
3
   SELECT TOP 1 WITH TIES
        Object_Name(c.object_id) ObjectName,
        c.name [Column Name],
        t.Name [Data type],
        c.max_length [Max Length]
    FROM    
        sys.columns c
    INNER JOIN 
        sys.types t ON c.system_type_id = t.system_type_id
    WHERE
        c.object_id = OBJECT_ID('MyTable')
    ORDER BY c.max_length DESC
于 2013-01-23T15:20:02.150 に答える
3



CeejeeBのソリューションを拡張して、新しいフィールド(Min、Max、NullCount、CountDinstict)を追加し、db名を取り巻くバグを[]で修正しました。
さらに、Unicodeタイプのサイズを管理しました。

変更されたSQLスクリプトを自由に試してみてください。ただし、スクリプトは現在のDBのすべてのユーザー定義テーブルを分析し、完​​了するまでに時間がかかる場合があるため、注意してください...

DECLARE @results TABLE (
    ID VARCHAR(36)
    ,TableName VARCHAR(250)
    ,ColumnName VARCHAR(250)
    ,DataType VARCHAR(250)
    ,MaxLength INT
    ,Longest INT
    ,Min VARCHAR(250)
    ,Max VARCHAR(250)
    ,NullCount BIGINT
    ,CountDistinct BIGINT
    ,SQLText VARCHAR(MAX)
    )

INSERT INTO @results (
    ID
    ,TableName
    ,ColumnName
    ,DataType
    ,MaxLength
    ,SQLText
    )
SELECT NEWID() AS ID
    ,Object_Name(c.object_id) AS TableName
    ,c.name AS ColumnName
    ,t.name AS DataType
    ,CASE 
        WHEN t.name NOT IN (
                'char'
                ,'varchar'
                ,'nchar'
                ,'nvarchar'
                ,'sysname'
                ,'text'
                )
            THEN c.max_length
        WHEN c.max_length = - 1
            THEN c.max_length
        ELSE CASE 
                WHEN t.name IN (
                        'nchar'
                        ,'nvarchar'
                        ,'sysname'
                        )
                    THEN c.max_length / 2
                ELSE c.max_length
                END
        END AS MaxLength
    ,'SELECT Max(Len(' + CASE t.name
        WHEN 'text'
            THEN 'cast('
        ELSE ''
        END + '[' + c.name + ']' + CASE t.name
        WHEN 'text'
            THEN ' as varchar(max))'
        ELSE ''
        END + ')) AS MaxLength,
        Min(' + CASE t.name
        WHEN 'bit'
            THEN 'CONVERT(int,'
        WHEN 'text'
            THEN 'cast('
        ELSE ''
        END + '[' + c.name + ']' + CASE t.name
        WHEN 'bit'
            THEN ')'
        WHEN 'text'
            THEN ' as varchar(max))'
        ELSE ''
        END + ') AS Min,
        Max(' + CASE t.name
        WHEN 'bit'
            THEN 'CONVERT(int,'
        WHEN 'text'
            THEN 'cast('
        ELSE ''
        END + '[' + c.name + ']' + CASE t.name
        WHEN 'bit'
            THEN ')'
        WHEN 'text'
            THEN ' as varchar(max))'
        ELSE ''
        END + ') AS Max, sum(case when ' + '[' + c.name + ']' + ' is null then 1 else 0 end) AS  NullCount, 
        COUNT_BIG(DISTINCT ' + CASE t.name
        WHEN 'text'
            THEN 'cast('
        ELSE ''
        END + '[' + c.name + ']' + CASE t.name
        WHEN 'text'
            THEN ' as varchar(max))'
        ELSE ''
        END + ') AS CountDistinct 
        FROM [' + OBJECT_SCHEMA_NAME(c.object_id) + '].[' + Object_Name(c.object_id) + ']' AS SQLText
FROM sys.columns c
INNER JOIN sys.types t ON c.system_type_id = t.system_type_id
INNER JOIN sys.objects o ON c.object_id = o.object_id
WHERE o.type = 'U'

DECLARE @id VARCHAR(36)
DECLARE @SQL VARCHAR(MAX)
DECLARE @receiver TABLE (
    Longest INT
    ,Min VARCHAR(250)
    ,Max VARCHAR(250)
    ,NullCount BIGINT
    ,CountDistinct BIGINT
    )

DECLARE length_cursor CURSOR
FOR
SELECT ID
    ,SQLText
FROM @results

OPEN length_cursor

FETCH NEXT
FROM length_cursor
INTO @id
    ,@SQL

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO @receiver (
        Longest
        ,Min
        ,Max
        ,NullCount
        ,CountDistinct
        )
    EXEC (@SQL)

    UPDATE @results
    SET Longest = r.Longest
        ,Min = r.Min
        ,Max = r.Max
        ,NullCount = r.NullCount
        ,CountDistinct = r.CountDistinct
    FROM @receiver r
    WHERE ID = @id

    DELETE
    FROM @receiver

    FETCH NEXT
    FROM length_cursor
    INTO @id
        ,@SQL
END

CLOSE length_cursor

DEALLOCATE length_cursor

SELECT TableName
    ,ColumnName
    ,DataType
    ,MaxLength
    ,Longest
    ,Min
    ,Max
    ,NullCount
    ,CountDistinct
FROM @results
于 2018-10-19T15:07:00.197 に答える
2

上記のクエリを修正

SELECT 
    Object_Name(c.object_id),
    c.name 'Column Name',
    t.name 'Data type',
    c.max_length 'Max Length'
FROM    
    sys.columns c
INNER JOIN 
    sys.types t ON c.user_type_id = t.user_type_id
WHERE
    c.object_id = OBJECT_ID('tablename')
于 2014-02-20T10:41:59.460 に答える
0

add:and t.user_type_id = 167それ以外の場合は、非varcharの重複が発生します。私は他のタイプがあることを知っています、それは特定のテーブルのための迅速な修正でした

c.object_id = OBJECT_ID(@YourTableName)の後

于 2015-04-30T22:16:57.170 に答える
0

上記のすべてのクエリは、いくつかの「奇妙な」サイズを報告することに注意してください-特にn ...タイプ(nvarchar / nchar)の場合。このわずかに変更されたクエリは、この問題を修正します。

DECLARE @tableName AS NVARCHAR(200) = 'Items'

SELECT 
    Object_Name(c.object_id) AS 'Table',
    c.name AS 'Column Name',
    t.name AS 'Data type',
    CASE WHEN t.name LIKE 'n%' THEN c.max_length / 2 ELSE c.max_length END AS 'Max Length'
FROM    
    sys.columns c
INNER JOIN 
    sys.types t ON c.user_type_id = t.user_type_id
WHERE
    c.object_id = OBJECT_ID(@tableName)
于 2017-07-07T09:11:30.657 に答える
0

最後にこれを理解して、テーブルの各列の最大データ長と最大長を見つけました

SELECT name, max_length, MAX(DATALENGTH(name))
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID('table name')
GROUP BY name, max_length
于 2020-10-08T17:35:18.867 に答える
0

TableA列とTableB列をサイズで比較するだけでは不十分です。tableAから各列データの最大データ長を取得し、それをTableB列サイズと比較して、原因の列を見つける必要があります。

于 2021-06-04T17:06:35.393 に答える
0

ほとんどの解決策を試しましたが、私にとってはこれだけでうまくいきました。説明の著者に感謝します。

最初の2行で、テーブル名とテーブルの場所をスキームにTableName変更するだけです。SchemaName正しいデータベースで実行していることを確認するか、

Use 
yourDatabse
go

このスクリプトの冒頭にあります。

/**************************************
SQL to get max length of values in every table column.

This SQL queries the specified table to get the max length
of all the values in every column.

To work, load all the incoming data into a "permanent" temporary table
where every column is defined as a varchar(max).

Then run this script against that "permanent" temporary table, comparing
the results against the original table's schema to see what column, and
then what record(s), is/are causing the issue.

Example, if the max length of a value in one of the columns is 270,
but your original table's schema is varchar(255), obviously either
the original table's schema will have to be altered or the data corrected.

Code from: http://cc.davelozinski.com
**************************************/

--The table we'll be performing this query on to get the lengths of every column.
--Default is dbo schema. Change as appropriate for your table.
DECLARE @TableName VARCHAR(200) = 'TableName'
       ,@SchemaName VARCHAR(200) = 'SchemaName'

DECLARE @MaxLengthDefault INT
       ,@Column VARCHAR(50)
       ,@MaxLength INT
       ,@MaxLengthString VARCHAR(10)
       ,@ColumnID INT
       ,@MaxColumnID INT
       ,@Command VARCHAR(2000)

CREATE TABLE #Temp (
       column_name VARCHAR(50)
       ,max_length INT
       ,max_length_default INT
)

SELECT @ColumnID = min(b.[column_id])
       ,@MaxColumnID = max(b.[column_id])
FROM sys.tables a
INNER JOIN sys.columns b on a.[object_id] = b.[object_id]
WHERE a.[name] = @TableName
       and SCHEMA_NAME(a.[schema_id]) = @SchemaName

--SELECT @ColumnID, @MaxColumnID

WHILE(@ColumnID <= @MaxColumnID)
BEGIN
    SET @Column = null

    SELECT @Column = b.[name]
              ,@MaxLengthDefault = b.[max_length]
       FROM sys.tables a
       INNER JOIN sys.columns b on a.[object_id] = b.[object_id]
       WHERE a.[name] = @TableName
              and SCHEMA_NAME(a.[schema_id]) = @SchemaName
              and b.[column_id] = @ColumnID

    --SELECT @Column, @MaxLengthDefault

    IF ( @Column is not null )
    BEGIN
              SET @Command = 'INSERT INTO #Temp(column_name, max_length, max_length_default)
                SELECT ''' + @Column + '''
                ,MAX(LEN(CAST([' + @Column + '] as VARCHAR(8000))))
                ,' + CAST(@MaxLengthDefault as VARCHAR(5)) +
                ' FROM [' + @SchemaName + '].[' + @TableName + ']
                WHERE [' + @Column + '] IS NOT NULL'
              --SELECT @Command
              EXEC(@Command)
       END

    SET @ColumnID = @ColumnID + 1
END

SELECT * FROM #Temp

DROP TABLE #Temp
于 2021-11-24T09:50:35.987 に答える
-1

答えはかなり複雑です。動的SQLを使用してクエリをまとめたり、Excelで作業を行ったりする必要があります。システムテーブルのメタデータ(Information_Schema.Columnsを使用します)をテーブル自体のデータと組み合わせる必要があります。

これを行う方法は、私の著書「 SQLとExcelを使用したデータ分析」の84〜90ページで説明されています。このサイトには答えが長すぎます。

于 2013-01-23T15:47:09.717 に答える
-2

以下のクエリを使用して、列名、データ型、列の長さを見つけることができます。

SELECT owner, 
       column_name, 
       data_type, 
       data_length 
FROM   all_tab_columns 
WHERE  table_name = 'write your table name here' 
       AND owner = 'write your column name here' 
ORDER  BY column_id; 

上記のクエリは、通常のクエリとPL/SQLの両方として機能します。

于 2020-01-23T06:35:08.383 に答える
-3

少し修正されましたが、扱います。

SELECT 
    Object_Name(c.object_id),
    c.name 'Column Name',
    t.name 'Data type',
    c.max_length 'Max Length',
    MAX(LEN(C.NAME))
FROM    
    sys.columns c
INNER JOIN 
    sys.types t ON c.user_type_id = t.user_type_id
WHERE
    c.object_id = OBJECT_ID('<table name>')
GROUP BY 
    Object_Name(c.object_id),
    c.name ,
    t.name ,
    c.max_length
于 2014-08-05T09:29:59.877 に答える