Search code examples
sqlschema

SQL statement to get column type


Is there a SQL statement that can return the type of a column in a table?


Solution

    • In ISO SQL (i.e. most RDBMS today) you can use the INFORMATION_SCHEMA.COLUMNS view, which SQL Server supports.
      • This view's DATA_TYPE column contains the T-SQL/SQL Server type names, except that it doesn't include arguments for parameterised types, which can result in unexpected/unintentional column behaviour.
        • For example, given three columns typed as nvarchar(max), datetime2(3), and decimal(10,5) then the output will be nvarchar, datetime2, and decimal respectively.
          • This is a problem because a column typed as nvarchar (without (max) or (123)) is the same as nvarchar(1), and using decimal is the same as decimal(18,0) which cannot store non-integer values.
        • The solution is to also look at CHARACTER_OCTET_LENGTH (for binary), CHARACTER_MAXIMUM_LENGTH (for char and nchar), DATETIME_PRECISION (for datetime2 and datetimeoffset), and NUMERIC_PRECISION with NUMERIC_SCALE (for decimal and numeric) in order to reconstruct the type's parameter values.
          • Note that float(n) can be ignored as SQL Server only supports float(24) and float(53) which are aliased by real and float respectively in the DATA_TYPE column.

    WITH q AS (
        
        SELECT
            c.TABLE_SCHEMA,
            c.TABLE_NAME,
            c.ORDINAL_POSITION,
            c.COLUMN_NAME,
            c.DATA_TYPE,
            CASE
                WHEN c.DATA_TYPE IN ( N'binary', N'varbinary'                    ) THEN ( CASE c.CHARACTER_OCTET_LENGTH   WHEN -1 THEN N'(max)' ELSE CONCAT( N'(', c.CHARACTER_OCTET_LENGTH  , N')' ) END )
                WHEN c.DATA_TYPE IN ( N'char', N'varchar', N'nchar', N'nvarchar' ) THEN ( CASE c.CHARACTER_MAXIMUM_LENGTH WHEN -1 THEN N'(max)' ELSE CONCAT( N'(', c.CHARACTER_MAXIMUM_LENGTH, N')' ) END )
                WHEN c.DATA_TYPE IN ( N'datetime2', N'datetimeoffset'            ) THEN CONCAT( N'(', c.DATETIME_PRECISION, N')' )
                WHEN c.DATA_TYPE IN ( N'decimal', N'numeric'                     ) THEN CONCAT( N'(', c.NUMERIC_PRECISION , N',', c.NUMERIC_SCALE, N')' )
            END AS DATA_TYPE_PARAMETER,
            CASE c.IS_NULLABLE
                WHEN N'NO'  THEN N' NOT NULL'
                WHEN N'YES' THEN     N' NULL'
            END AS IS_NULLABLE2
        FROM
            INFORMATION_SCHEMA.COLUMNS AS c
    )
    SELECT
        q.TABLE_SCHEMA,
        q.TABLE_NAME,
        q.ORDINAL_POSITION,
        q.COLUMN_NAME,
        CONCAT( q.DATA_TYPE, ISNULL( q.DATA_TYPE_PARAMETER, N'' ), q.IS_NULLABLE2 ) AS FULL_DATA_TYPE
    
    FROM
        q
    WHERE
        q.TABLE_SCHEMA = 'yourSchemaName' AND
        q.TABLE_NAME   = 'yourTableName'  AND 
        q.COLUMN_NAME  = 'yourColumnName'
    
    ORDER BY
        q.TABLE_SCHEMA,
        q.TABLE_NAME,
        q.ORDINAL_POSITION;
    

    Gives results like this:

    enter image description here