Back to all posts

How to find table column information by using SQL query

Comprehensive Guide to Fetching Table and Column Metadata with SQL Server Stored Procedures When working with databases, understanding the structure of tab…

Comprehensive Guide to Fetching Table and Column Metadata with SQL Server Stored Procedures

When working with databases, understanding the structure of tables, columns, constraints, and relationships is crucial for effective database management and development. This blog explores a robust SQL Server stored procedure that retrieves detailed metadata about a table, including column data types, constraints, primary and foreign keys, default values, and much more.


Why Metadata Matters?

Database metadata provides a clear overview of the structure and relationships of database objects. It helps:

  • Auditing database structure.
  • Planning migrations or schema changes.
  • Debugging and resolving issues.
  • Enhancing collaboration between teams by ensuring everyone has a clear view of the database schema.

Stored Procedure Overview

The stored procedure SP_GetTableColumnInfo allows you to extract detailed metadata for any given table in a SQL Server database. Here's what it provides:

  1. Column Details:
    • Name, data type, nullability, and default values.
  2. Constraint Information:
    • Primary and foreign keys, associated constraint names.
  3. Relationships:
    • Foreign key references to other tables and columns.
  4. Constraint Audits:
    • Old and proposed constraint names.
    • Default value consistency checks.

The Stored Procedure

Here's the complete script for SP_GetTableColumnInfo:

SQL
CREATE PROCEDURE SP_GetTableColumnInfo
    @TableName NVARCHAR(255)
AS
BEGIN
    SELECT
        colInfo.TABLE_NAME AS 'Table Name',
        colInfo.COLUMN_NAME AS 'Column Name',
        colInfo.DATA_TYPE
            + CASE
                WHEN colInfo.DATA_TYPE IN ('varchar', 'nvarchar') THEN '(' + CAST(colInfo.CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) + ')'
                WHEN colInfo.DATA_TYPE = 'decimal' THEN '(' + CAST(colInfo.NUMERIC_PRECISION AS VARCHAR(10)) + ',' + CAST(colInfo.NUMERIC_SCALE AS VARCHAR(10)) + ')'
                ELSE ''
              END AS 'Data Type',
        colInfo.IS_NULLABLE AS 'Allow Null',
        ISNULL(colInfo.COLUMN_DEFAULT, '') AS 'Default Value',
        ISNULL(sep.value, '') AS 'Description',
        '' AS 'Remarks',
        ISNULL(tc.CONSTRAINT_NAME, '') AS 'Constraint Name',
        CASE
            WHEN tc.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 'Yes'
            ELSE 'No'
        END AS 'Primary Key',
        CASE
            WHEN fk.CONSTRAINT_NAME IS NOT NULL THEN 'Yes'
            ELSE 'No'
        END AS 'Foreign Key',
        ISNULL(fk.ReferencedTableName, '') AS 'Referenced Table',
        ISNULL(fk.ReferencedColumnName, '') AS 'Referenced Column',
        ISNULL(dc.name, '') AS 'Old Constraint',
        'DF_' + t.name + '_' + c.name AS 'Name Will Be',
        REPLACE(REPLACE(dc.definition, '(', ''), ')', '') AS 'Old Default Value',
        CASE
            WHEN dc.name = 'DF_' + t.name + '_' + c.name THEN 1 
            ELSE 0 
        END AS 'Is Constraint Matching',
        CASE
            WHEN TYPE_NAME(c.user_type_id) IN ('smallint', 'int', 'tinyint', 'bit', 'bigint', 'decimal', 'float') THEN '0'
            WHEN TYPE_NAME(c.user_type_id) IN ('varchar', 'nvarchar', 'char', 'nchar', 'text') THEN ''''''
            WHEN TYPE_NAME(c.user_type_id) IN ('datetime', 'date', 'smalldatetime', 'datetime2', 'datetimeoffset') THEN NULL
            ELSE 'N/A'
        END AS 'Default Value Will Be',
        CASE
            WHEN REPLACE(REPLACE(dc.definition, '(', ''), ')', '') = 
                 CASE
                     WHEN TYPE_NAME(c.user_type_id) IN ('smallint', 'int', 'tinyint', 'bit', 'bigint', 'decimal', 'float') THEN '0'
                     WHEN TYPE_NAME(c.user_type_id) IN ('varchar', 'nvarchar', 'char', 'nchar', 'text') THEN ''''''
                     WHEN TYPE_NAME(c.user_type_id) IN ('datetime', 'date', 'smalldatetime', 'datetime2', 'datetimeoffset') THEN NULL
                     ELSE 'N/A'
                 END
            THEN 1
            ELSE 0
        END AS 'Is Default Matching'
    FROM
        INFORMATION_SCHEMA.COLUMNS colInfo
        LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu ON colInfo.TABLE_NAME = ccu.TABLE_NAME 
                                                                   AND colInfo.COLUMN_NAME = ccu.COLUMN_NAME
        LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON ccu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
                                                           AND ccu.TABLE_NAME = tc.TABLE_NAME
        LEFT JOIN (
            SELECT 
                fk.name AS CONSTRAINT_NAME,
                fkc.parent_object_id,
                fkc.parent_column_id,
                OBJECT_NAME(fkc.referenced_object_id) AS ReferencedTableName,
                col.name AS ReferencedColumnName
            FROM 
                sys.foreign_keys fk
                INNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id
                INNER JOIN sys.columns col ON fkc.referenced_object_id = col.object_id
                                            AND fkc.referenced_column_id = col.column_id
        ) fk ON OBJECT_ID(colInfo.TABLE_NAME) = fk.parent_object_id 
               AND colInfo.ORDINAL_POSITION = fk.parent_column_id
        LEFT JOIN sys.tables t ON t.name = colInfo.TABLE_NAME
        LEFT JOIN sys.columns c ON c.object_id = t.object_id AND c.name = colInfo.COLUMN_NAME
        LEFT JOIN sys.default_constraints dc ON c.default_object_id = dc.object_id
        LEFT JOIN sys.extended_properties sep ON c.object_id = sep.major_id
                                               AND c.column_id = sep.minor_id
                                               AND sep.name = 'MS_Description'
    WHERE
        colInfo.TABLE_NAME = @TableName
    ORDER BY
        colInfo.TABLE_NAME,
        colInfo.ORDINAL_POSITION;
END;

Key Features

1. Column Metadata:

Retrieves comprehensive details for each column, such as:

  • Data types with precision (e.g., varchar(255)).
  • Nullability (Allow Null).

2. Constraints:

Shows all constraints associated with the columns:

  • Primary Keys.
  • Foreign Keys, including the referenced table and column.

3. Constraint Auditing:

  • Old constraint names and proposed names (Name Will Be).
  • Verifies whether default constraints are named correctly (Is Constraint Matching).
  • Checks if default values align with data type requirements (Is Default Matching).

4. Descriptions:

Fetches extended properties (MS_Description) for columns, enabling better documentation.


Example Execution

To fetch metadata for the DimCustomer table:

SQL
EXEC SP_GetTableColumnInfo 'DimCustomer';

Sample Output


Use Cases

  1. Auditing Schema: Ensure constraints and default values are correctly defined and named.
  2. Database Migrations: Generate a clear schema blueprint before transitioning databases.
  3. Code Generation: Use metadata to auto-generate models or data layer scripts in applications.
  4. Data Quality Checks: Identify mismatches in constraints or default value definitions.

Conclusion

This stored procedure is a powerful tool for database administrators and developers alike, offering insights into table structure and integrity. By automating metadata extraction, it simplifies database management and fosters better understanding of the schema.

Feel free to customize this procedure further based on your specific needs. Let us know how this procedure has helped streamline your workflow!

Keep building your data skillset

Explore more SQL, Python, analytics, and engineering tutorials.