Profiling the metadata and data in every column in every table is frequently done by a purchased package. Doing it yourself is a rather big undertaking. Most approaches will do a full table scan (FTS) for every column in the table. This could be unacceptably time-consuming. The following script will collect this data from the source tables 50 columns at a time in a single pass.
The data collected will show for every table and column the following information in a [Column_Profile] table:
- Schema Name
- Table Name
- Column_ID
- Column Name
- Extended Property
- [Column Name] (shown with square parentheses and embedded spaces)
- [Keep] (a subjective determination whether the column has any significant data; e.g. all NULL or only one value.)
- Percentage data with non-NULL values
- Data Type
- data_type_ext (includes size definition)
- Is the column Nullable? Yes/No
- Default_Value
- Is a Primary Key column "PK"
- Is a Foreign Key column "FK"
- Is a Unique Key column "UK"
- Check_Contraint
- Computed Column Definition
- Column Collation Map
- Number of Records
- Number of Not NULL Values
- Number of Distinct Values
- Minimum Value in this column over the table (this is a SQL_VARIANT column)
- Maximum Value in this column
DROP TABLE IF EXISTS [dbo].[Column_Profile_50];
--Create staging table to hold data profile.
CREATE TABLE [dbo].[Column_Profile_50]
( [SchemaName] varchar(50) NOT NULL
, [TableName] varchar(50) NOT NULL
, [Records] int NULL
, c1 varchar(70) --[ColumnName]
, n1 int --[Not_NULL]
, d1 int --[Distinct_Values]
, a1 SQL_VARIANT --[Min_Value]
, b1 SQL_VARIANT --[Max_Value]
, c2 varchar(70), n2 int, d2 int, a2 SQL_VARIANT, b2 SQL_VARIANT
, c3 varchar(70), n3 int, d3 int, a3 SQL_VARIANT, b3 SQL_VARIANT
, c4 varchar(70), n4 int, d4 int, a4 SQL_VARIANT, b4 SQL_VARIANT
, c5 varchar(70), n5 int, d5 int, a5 SQL_VARIANT, b5 SQL_VARIANT
, c6 varchar(70), n6 int, d6 int, a6 SQL_VARIANT, b6 SQL_VARIANT
, c7 varchar(70), n7 int, d7 int, a7 SQL_VARIANT, b7 SQL_VARIANT
, c8 varchar(70), n8 int, d8 int, a8 SQL_VARIANT, b8 SQL_VARIANT
, c9 varchar(70), n9 int, d9 int, a9 SQL_VARIANT, b9 SQL_VARIANT
, c10 varchar(70), n10 int, d10 int, a10 SQL_VARIANT, b10 SQL_VARIANT
, c11 varchar(70), n11 int, d11 int, a11 SQL_VARIANT, b11 SQL_VARIANT
, c12 varchar(70), n12 int, d12 int, a12 SQL_VARIANT, b12 SQL_VARIANT
, c13 varchar(70), n13 int, d13 int, a13 SQL_VARIANT, b13 SQL_VARIANT
, c14 varchar(70), n14 int, d14 int, a14 SQL_VARIANT, b14 SQL_VARIANT
, c15 varchar(70), n15 int, d15 int, a15 SQL_VARIANT, b15 SQL_VARIANT
, c16 varchar(70), n16 int, d16 int, a16 SQL_VARIANT, b16 SQL_VARIANT
, c17 varchar(70), n17 int, d17 int, a17 SQL_VARIANT, b17 SQL_VARIANT
, c18 varchar(70), n18 int, d18 int, a18 SQL_VARIANT, b18 SQL_VARIANT
, c19 varchar(70), n19 int, d19 int, a19 SQL_VARIANT, b19 SQL_VARIANT
, c20 varchar(70), n20 int, d20 int, a20 SQL_VARIANT, b20 SQL_VARIANT
, c21 varchar(70), n21 int, d21 int, a21 SQL_VARIANT, b21 SQL_VARIANT
, c22 varchar(70), n22 int, d22 int, a22 SQL_VARIANT, b22 SQL_VARIANT
, c23 varchar(70), n23 int, d23 int, a23 SQL_VARIANT, b23 SQL_VARIANT
, c24 varchar(70), n24 int, d24 int, a24 SQL_VARIANT, b24 SQL_VARIANT
, c25 varchar(70), n25 int, d25 int, a25 SQL_VARIANT, b25 SQL_VARIANT
, c26 varchar(70), n26 int, d26 int, a26 SQL_VARIANT, b26 SQL_VARIANT
, c27 varchar(70), n27 int, d27 int, a27 SQL_VARIANT, b27 SQL_VARIANT
, c28 varchar(70), n28 int, d28 int, a28 SQL_VARIANT, b28 SQL_VARIANT
, c29 varchar(70), n29 int, d29 int, a29 SQL_VARIANT, b29 SQL_VARIANT
, c30 varchar(70), n30 int, d30 int, a30 SQL_VARIANT, b30 SQL_VARIANT
, c31 varchar(70), n31 int, d31 int, a31 SQL_VARIANT, b31 SQL_VARIANT
, c32 varchar(70), n32 int, d32 int, a32 SQL_VARIANT, b32 SQL_VARIANT
, c33 varchar(70), n33 int, d33 int, a33 SQL_VARIANT, b33 SQL_VARIANT
, c34 varchar(70), n34 int, d34 int, a34 SQL_VARIANT, b34 SQL_VARIANT
, c35 varchar(70), n35 int, d35 int, a35 SQL_VARIANT, b35 SQL_VARIANT
, c36 varchar(70), n36 int, d36 int, a36 SQL_VARIANT, b36 SQL_VARIANT
, c37 varchar(70), n37 int, d37 int, a37 SQL_VARIANT, b37 SQL_VARIANT
, c38 varchar(70), n38 int, d38 int, a38 SQL_VARIANT, b38 SQL_VARIANT
, c39 varchar(70), n39 int, d39 int, a39 SQL_VARIANT, b39 SQL_VARIANT
, c40 varchar(70), n40 int, d40 int, a40 SQL_VARIANT, b40 SQL_VARIANT
, c41 varchar(70), n41 int, d41 int, a41 SQL_VARIANT, b41 SQL_VARIANT
, c42 varchar(70), n42 int, d42 int, a42 SQL_VARIANT, b42 SQL_VARIANT
, c43 varchar(70), n43 int, d43 int, a43 SQL_VARIANT, b43 SQL_VARIANT
, c44 varchar(70), n44 int, d44 int, a44 SQL_VARIANT, b44 SQL_VARIANT
, c45 varchar(70), n45 int, d45 int, a45 SQL_VARIANT, b45 SQL_VARIANT
, c46 varchar(70), n46 int, d46 int, a46 SQL_VARIANT, b46 SQL_VARIANT
, c47 varchar(70), n47 int, d47 int, a47 SQL_VARIANT, b47 SQL_VARIANT
, c48 varchar(70), n48 int, d48 int, a48 SQL_VARIANT, b48 SQL_VARIANT
, c49 varchar(70), n49 int, d49 int, a49 SQL_VARIANT, b49 SQL_VARIANT
, c50 varchar(70), n50 int, d50 int, a50 SQL_VARIANT, b50 SQL_VARIANT
)
--SELECT * FROM [dbo].[Column_Profile_50];
--TRUNCATE TABLE [dbo].[Column_Profile_50];
--Collect column profile data 50 columns at a time in Full Table Scans.
DECLARE @table_schema varchar(100)
DECLARE @table_name varchar(100)
DECLARE @column_name varchar(100)
DECLARE @current_table varchar(100)
DECLARE @current_schema varchar(100)
DECLARE @sql varchar(MAX)
DECLARE @sql1 varchar(MAX)
DECLARE @sql2 varchar(MAX)
DECLARE @col int = 0
--Get columns for data profile.
DECLARE Cursor01 CURSOR LOCAL FAST_FORWARD FOR
SELECT A.TABLE_SCHEMA, A.TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS a
-- left join [DW].[Column_Profile_temp] x on a.TABLE_SCHEMA=x.SchemaName and a.TABLE_NAME=x.tableName and concat('[',a.COLUMN_NAME,']')=x.columnname --this is to continue after failure
-- where x.TableName is null
WHERE DATA_TYPE not in ('bit','text','ntext') --Do not profile data in columns with these datatypes.
AND CHARACTER_OCTET_LENGTH <> -1
-- AND a.TABLE_SCHEMA = 'Financials' --Change this filter if needed.
-- AND a.TABLE_NAME NOT LIKE '%TEST%'
order by 1,2,3
OPEN Cursor01;
FETCH NEXT FROM Cursor01 into @table_schema, @table_name, @column_name;
WHILE @@FETCH_STATUS = 0
BEGIN
--If new table then start building query
IF @col=0
BEGIN
set @sql1 = 'insert into [dbo].Column_Profile_50 (SchemaName, TableName, Records'
set @sql2 = replace(replace('select ''!'', ''^'', count(*)', '^',@table_name), '!',@table_schema)
END
--Add column to query
set @col=@col+1
set @sql1=concat(@sql1, replace(', c^, n^, d^, a^, b^', '^', @col))
set @sql2=concat(@sql2, replace(', ''[?]'', count([?]), count(distinct [?]), min([?]), max([?])', '?',@column_name))
--Get next column
set @current_table = @table_name
set @current_schema = @table_schema
FETCH NEXT FROM Cursor01 into @table_schema, @table_name, @column_name;
--If table name changed then finish query and execute
IF @table_name<>@current_table OR @col=50 OR @@FETCH_STATUS <> 0
BEGIN
set @sql=concat(@sql1, ') ', @sql2, replace(replace(' from !.[^];', '^', @current_table), '!', @current_schema))
PRINT @sql
EXEC(@sql)
set @col=0
END
END
CLOSE Cursor01;
DEALLOCATE Cursor01;
GO
DROP TABLE IF EXISTS [dbo].[Column_Profile_temp]
CREATE TABLE [dbo].[Column_Profile_temp](
[SchemaName] [varchar](50) NOT NULL,
[TableName] [varchar](50) NOT NULL,
[ColumnName] [varchar](70) NOT NULL,
[Records] [int] NULL,
[Not_NULL] [int] NULL,
[Distinct_Values] [int] NULL,
[Min_Value] SQL_VARIANT,
[Max_Value] SQL_VARIANT
)
--Convert from 50 source columns per row to 1 row per source column.
INSERT INTO [dbo].[Column_Profile_temp]
SELECT [SchemaName], [TableName], c1, [Records], n1, d1, a1, b1 FROM [dbo].[Column_Profile_50] WHERE c1 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c2, [Records], n2, d2, a2, b2 FROM [dbo].[Column_Profile_50] WHERE c2 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c3, [Records], n3, d3, a3, b3 FROM [dbo].[Column_Profile_50] WHERE c3 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c4, [Records], n4, d4, a4, b4 FROM [dbo].[Column_Profile_50] WHERE c4 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c5, [Records], n5, d5, a5, b5 FROM [dbo].[Column_Profile_50] WHERE c5 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c6, [Records], n6, d6, a6, b6 FROM [dbo].[Column_Profile_50] WHERE c6 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c7, [Records], n7, d7, a7, b7 FROM [dbo].[Column_Profile_50] WHERE c7 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c8, [Records], n8, d8, a8, b8 FROM [dbo].[Column_Profile_50] WHERE c8 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c9, [Records], n9, d9, a9, b9 FROM [dbo].[Column_Profile_50] WHERE c9 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c10, [Records], n10, d10, a10, b10 FROM [dbo].[Column_Profile_50] WHERE c10 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c11, [Records], n11, d11, a11, b11 FROM [dbo].[Column_Profile_50] WHERE c11 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c12, [Records], n12, d12, a12, b12 FROM [dbo].[Column_Profile_50] WHERE c12 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c13, [Records], n13, d13, a13, b13 FROM [dbo].[Column_Profile_50] WHERE c13 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c14, [Records], n14, d14, a14, b14 FROM [dbo].[Column_Profile_50] WHERE c14 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c15, [Records], n15, d15, a15, b15 FROM [dbo].[Column_Profile_50] WHERE c15 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c16, [Records], n16, d16, a16, b16 FROM [dbo].[Column_Profile_50] WHERE c16 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c17, [Records], n17, d17, a17, b17 FROM [dbo].[Column_Profile_50] WHERE c17 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c18, [Records], n18, d18, a18, b18 FROM [dbo].[Column_Profile_50] WHERE c18 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c19, [Records], n19, d19, a19, b19 FROM [dbo].[Column_Profile_50] WHERE c19 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c20, [Records], n20, d20, a20, b20 FROM [dbo].[Column_Profile_50] WHERE c20 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c21, [Records], n21, d21, a21, b21 FROM [dbo].[Column_Profile_50] WHERE c21 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c22, [Records], n22, d22, a22, b22 FROM [dbo].[Column_Profile_50] WHERE c22 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c23, [Records], n23, d23, a23, b23 FROM [dbo].[Column_Profile_50] WHERE c23 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c24, [Records], n24, d24, a24, b24 FROM [dbo].[Column_Profile_50] WHERE c24 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c25, [Records], n25, d25, a25, b25 FROM [dbo].[Column_Profile_50] WHERE c25 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c26, [Records], n26, d26, a26, b26 FROM [dbo].[Column_Profile_50] WHERE c26 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c27, [Records], n27, d27, a27, b27 FROM [dbo].[Column_Profile_50] WHERE c27 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c28, [Records], n28, d28, a28, b28 FROM [dbo].[Column_Profile_50] WHERE c28 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c29, [Records], n29, d29, a29, b29 FROM [dbo].[Column_Profile_50] WHERE c29 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c30, [Records], n30, d30, a30, b30 FROM [dbo].[Column_Profile_50] WHERE c30 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c31, [Records], n31, d31, a31, b31 FROM [dbo].[Column_Profile_50] WHERE c31 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c32, [Records], n32, d32, a32, b32 FROM [dbo].[Column_Profile_50] WHERE c32 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c33, [Records], n33, d33, a33, b33 FROM [dbo].[Column_Profile_50] WHERE c33 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c34, [Records], n34, d34, a34, b34 FROM [dbo].[Column_Profile_50] WHERE c34 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c35, [Records], n35, d35, a35, b35 FROM [dbo].[Column_Profile_50] WHERE c35 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c36, [Records], n36, d36, a36, b36 FROM [dbo].[Column_Profile_50] WHERE c36 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c37, [Records], n37, d37, a37, b37 FROM [dbo].[Column_Profile_50] WHERE c37 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c38, [Records], n38, d38, a38, b38 FROM [dbo].[Column_Profile_50] WHERE c38 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c39, [Records], n39, d39, a39, b39 FROM [dbo].[Column_Profile_50] WHERE c39 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c40, [Records], n40, d40, a40, b40 FROM [dbo].[Column_Profile_50] WHERE c40 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c41, [Records], n41, d41, a41, b41 FROM [dbo].[Column_Profile_50] WHERE c41 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c42, [Records], n42, d42, a42, b42 FROM [dbo].[Column_Profile_50] WHERE c42 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c43, [Records], n43, d43, a43, b43 FROM [dbo].[Column_Profile_50] WHERE c43 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c44, [Records], n44, d44, a44, b44 FROM [dbo].[Column_Profile_50] WHERE c44 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c45, [Records], n45, d45, a45, b45 FROM [dbo].[Column_Profile_50] WHERE c45 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c46, [Records], n46, d46, a46, b46 FROM [dbo].[Column_Profile_50] WHERE c46 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c47, [Records], n47, d47, a47, b47 FROM [dbo].[Column_Profile_50] WHERE c47 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c48, [Records], n48, d48, a48, b48 FROM [dbo].[Column_Profile_50] WHERE c48 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c49, [Records], n49, d49, a49, b49 FROM [dbo].[Column_Profile_50] WHERE c49 IS NOT NULL UNION ALL
SELECT [SchemaName], [TableName], c50, [Records], n50, d50, a50, b50 FROM [dbo].[Column_Profile_50] WHERE c50 IS NOT NULL
ORDER BY 1,2,3;
GO
DROP TABLE IF EXISTS [dbo].[Column_Profile];
CREATE TABLE [dbo].Column_Profile(
[Schema_Name] nvarchar(128) NULL,
Table_Name sysname NOT NULL,
Column_ID int NULL,
Column_Name sysname NOT NULL,
Extended_Property SQL_VARIANT NULL,
[Column Name] varchar(130) NULL,
[Keep] varchar(1) NULL,
Pct_Valued int NULL,
Data_Type sysname NULL,
data_type_ext nvarchar(269) NULL,
Nullable varchar(3) NULL,
Default_Value nvarchar(max) NULL,
Primary_Key varchar(2) NULL,
Foreign_Key varchar(2) NULL,
Unique_Key varchar(2) NULL,
Check_contraint varchar(5) NULL,
computed_column_definition nvarchar(max) NULL,
ColumnCollation varchar(50),
Records int NULL,
Not_NULL int NULL,
Distinct_Values int NULL,
Min_Value SQL_VARIANT,
Max_Value SQL_VARIANT
)
GO
--Load column profile.
INSERT INTO [dbo].[Column_Profile]
SELECT schema_name(tbl.schema_id) AS Schema_Name
,tbl.NAME AS Table_Name
,col.Column_ID
,col.NAME AS Column_Name
,ep.value AS Extended_Property
,'['+TRIM(CAST(eq.value AS VARCHAR(50)))+' - '+TRIM(CAST(ep.value AS VARCHAR(75)))+']' AS [Column Name]
,case
when ep.value is NULL THEN 'N'
when P.[Records] < 2 then 'N'
when P.[Distinct_Values] = 1 then 'N'
-- when 100.0*P.[Not_NULL]/CASE P.[Records] when 0 then 1 else P.[Records] end < 10 then 'N'
when CAST(P.[Not_NULL] AS FLOAT)/CAST(P.[Records] AS FLOAT) < 0.005 then 'N'
else 'Y'
end AS Keep --Determine if this column has any significant data (this is subjective).
,FLOOR(100.0*P.[Not_NULL]/CASE P.[Records] when 0 then 1 else P.[Records] end) AS Pct_Valued
,t.NAME AS Data_Type
,t.NAME
+ CASE
WHEN t.is_user_defined = 0
THEN isnull( '(' +
CASE
WHEN t.NAME IN ('binary', 'char', 'nchar', 'varchar', 'nvarchar', 'varbinary')
THEN
CASE col.max_length
WHEN - 1
THEN 'MAX'
ELSE
CASE
WHEN t.NAME IN ('nchar', 'nvarchar')
THEN cast(col.max_length / 2 AS VARCHAR(4))
ELSE cast(col.max_length AS VARCHAR(4))
END
END
WHEN t.NAME IN ('datetime2', 'datetimeoffset', 'time')
THEN cast(col.scale AS VARCHAR(4))
WHEN t.NAME IN ('decimal', 'numeric')
THEN cast(col.precision AS VARCHAR(4)) + ', ' + cast(col.scale AS VARCHAR(4))
END + ')', '')
ELSE ':' + (
SELECT c_t.NAME + isnull('(' +
CASE
WHEN c_t.NAME IN ('binary', 'char', 'nchar', 'varchar', 'nvarchar', 'varbinary')
THEN
CASE c.max_length
WHEN - 1
THEN 'MAX'
ELSE
CASE
WHEN t.NAME IN ('nchar', 'nvarchar')
THEN cast(c.max_length / 2 AS VARCHAR(4))
ELSE cast(c.max_length AS VARCHAR(4))
END
END
WHEN c_t.NAME IN ('datetime2', 'datetimeoffset', 'time')
THEN cast(c.scale AS VARCHAR(4))
WHEN c_t.NAME IN ('decimal', 'numeric')
THEN cast(c.precision AS VARCHAR(4)) + ', ' + cast(c.scale AS VARCHAR(4))
END + ')', '')
FROM sys.columns AS c
INNER JOIN sys.types AS c_t ON c.system_type_id = c_t.user_type_id
WHERE c.object_id = col.object_id AND c.column_id = col.column_id AND c.user_type_id = col.user_type_id
)
END AS data_type_ext
,CASE WHEN col.is_nullable = 0 THEN 'No' ELSE 'Yes' END AS Nullable
,CASE WHEN def.DEFINITION IS NOT NULL THEN def.DEFINITION ELSE '' END AS Default_Value
,CASE WHEN pk.column_id IS NOT NULL THEN 'PK' ELSE '' END AS Primary_Key
,CASE WHEN fk.parent_column_id IS NOT NULL THEN 'FK' ELSE '' END AS Foreign_Key
,CASE WHEN uk.column_id IS NOT NULL THEN 'UK' ELSE '' END AS Unique_Key
,CASE WHEN ch.check_const IS NOT NULL THEN ch.check_const ELSE '' END AS Check_contraint
,cc.DEFINITION AS computed_column_definition
,col.collation_name AS ColumnCollation
,P.[Records]
,P.[Not_NULL]
,P.[Distinct_Values]
,P.[Min_Value]
,P.[Max_Value]
FROM sys.tables AS tbl
JOIN sys.columns AS col ON tbl.object_id = col.object_id
JOIN sys.types AS t ON col.user_type_id = t.user_type_id
LEFT JOIN sys.default_constraints AS def ON def.object_id = col.default_object_id
LEFT JOIN (
SELECT index_columns.object_id, index_columns.column_id
FROM sys.index_columns
INNER JOIN sys.indexes ON index_columns.object_id = indexes.object_id AND index_columns.index_id = indexes.index_id
WHERE indexes.is_primary_key = 1
) AS pk ON col.object_id = pk.object_id AND col.column_id = pk.column_id
LEFT JOIN (
SELECT fc.parent_column_id, fc.parent_object_id
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id
GROUP BY fc.parent_column_id, fc.parent_object_id
) AS fk ON fk.parent_object_id = col.object_id AND fk.parent_column_id = col.column_id
LEFT JOIN (
SELECT c.parent_column_id, c.parent_object_id, 'Check' check_const
FROM sys.check_constraints AS c
GROUP BY c.parent_column_id, c.parent_object_id
) AS ch ON col.column_id = ch.parent_column_id AND col.object_id = ch.parent_object_id
LEFT JOIN (
SELECT index_columns.object_id, index_columns.column_id
FROM sys.index_columns
INNER JOIN sys.indexes ON indexes.index_id = index_columns.index_id AND indexes.object_id = index_columns.object_id
WHERE indexes.is_unique_constraint = 1
GROUP BY index_columns.object_id, index_columns.column_id
) AS uk ON col.column_id = uk.column_id AND col.object_id = uk.object_id
LEFT JOIN sys.extended_properties AS eq ON eq.major_id=tbl.object_id AND eq.minor_id=0 AND eq.class=1 AND eq.NAME = 'MS_Description'
LEFT JOIN sys.extended_properties AS ep
ON tbl.object_id = ep.major_id
AND col.column_id = ep.minor_id
AND ep.NAME = 'MS_Description'
AND ep.class_desc = 'OBJECT_OR_COLUMN'
LEFT JOIN sys.computed_columns AS cc ON tbl.object_id = cc.object_id AND col.column_id = cc.column_id
LEFT JOIN [dbo].[Column_Profile_temp] P ON P.SchemaName = schema_name(tbl.schema_id) AND P.TableName = tbl.NAME AND P.ColumnName = CONCAT('[',col.NAME,']') --If you created this table
--WHERE SCHEMA_NAME(tbl.schema_id) = 'Financials' --Filter if needed.
--AND tbl.TABLE_NAME NOT LIKE '%TEST%'
ORDER BY 1,2,3;
GO
SELECT * FROM [dbo].[Column_Profile] ORDER BY 1,2,3
GO