Get Database Extended Properties

Applicability:

SQL Server 2000: N/A

SQL Server 2005: Tested

SQL Server 2008: Tested

SQL Server 2008R2: Tested

SQL Server 2012: Tested

SQL Server 2014: Tested

SQL Server 2016: Tested

SQL Server 2017: Not Tested

Credits:

Author:Phil Factor/ChillyDBA

Date: 5 Jun 2020

Description

3 queries to produce lists of Extended Properties for a database

Either a full list, objects only or objects and columns

Useful for database documentation

Code

Get a detail list of all Database Extended Properties

--get all extended properties for a database


SELECT --we start off by listing objects AND columns that are documented

CASE WHEN ob.parent_object_id > 0 THEN

OBJECT_SCHEMA_NAME(ob.parent_object_id) + '.'

+ OBJECT_NAME(ob.parent_object_id) + '.' + ob.name

ELSE OBJECT_SCHEMA_NAME(ob.object_id) + '.' + ob.name

END + CASE WHEN ep.minor_id > 0 THEN '.' + col.name ELSE '' END AS path,

'schema' + CASE WHEN ob.parent_object_id > 0 THEN '/table' ELSE '' END

+ '/' +CASE WHEN ob.type_desc LIKE '%constraint%'

THEN CASE WHEN OBJECTPROPERTYEX(ob.object_id, 'CnstIsColumn') = 1

THEN 'column_level_' ELSE 'table_level_'END

ELSE '' END

+CASE WHEN ob.type IN

( 'TF', 'FN', 'IF', 'FS', 'FT' ) THEN 'function'

WHEN ob.type IN ( 'P', 'PC', 'RF', 'X' ) THEN 'procedure'

WHEN ob.type IN ( 'U', 'IT' ) THEN 'table'

WHEN ob.type = 'SQ' THEN 'queue'

ELSE LOWER(ob.type_desc)

END

+ CASE WHEN col.column_id IS NULL THEN '' ELSE '/column' END AS thing,

ep.value

FROM sys.extended_properties ep

INNER JOIN sys.objects ob

ON ep.major_id = ob.object_id AND ep.class = 1

LEFT OUTER JOIN sys.columns col

ON ep.major_id = col.object_id

AND ep.class = 1

AND ep.minor_id = col.column_id

AND ep.name = 'MS_Description'




UNION ALL

SELECT --indexes

OBJECT_SCHEMA_NAME(ix.object_id) + '.' + OBJECT_NAME(ix.object_id) + '.'

+ ix.name,

'schema/'

+ CASE WHEN OBJECTPROPERTYEX(ix.object_id, 'BaseType') = 'U' THEN 'table'

ELSE 'view'

END + '/index', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.indexes ix

ON ep.major_id = ix.object_id

AND ep.class = 7

AND ep.minor_id = ix.index_id

WHERE ep.name = 'MS_Description'

UNION ALL

SELECT --Parameters

OBJECT_SCHEMA_NAME(ob.object_id) + '.' + OBJECT_NAME(ob.object_id) + '.'

+ par.name, 'schema/' + LOWER(ob.type_desc) + '/parameter', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.objects ob

ON ep.major_id = ob.object_id AND ep.class = 2

INNER JOIN sys.parameters par

ON ep.major_id = par.object_id

AND ep.class = 2

AND ep.minor_id = par.parameter_id

WHERE ep.name = 'MS_Description'


UNION ALL

SELECT --schemas

sch.name, 'schema', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.schemas sch

ON ep.class = 3

AND ep.name = 'MS_Description'

AND ep.major_id = sch.schema_id


UNION ALL --Database

SELECT DB_NAME(), '', ep.value

FROM sys.extended_properties ep

WHERE ep.class = 0

UNION ALL --XML Schema Collections

SELECT SCHEMA_NAME(xc.schema_id) + '.' + xc.name,

'schema/xml_Schema_collection', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.xml_schema_collections xc

ON ep.class = 10

AND ep.name = 'MS_Description'

AND ep.major_id = xc.xml_collection_id

UNION ALL

SELECT --Database Files

df.name, 'database_file', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.database_files df

ON ep.class = 22

AND ep.name = 'MS_Description'

AND ep.major_id = df.file_id

UNION ALL

SELECT --Data Spaces

ds.name, 'dataspace', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.data_spaces ds

ON ep.class = 20

AND ep.name = 'MS_Description'

AND ep.major_id = ds.data_space_id


UNION ALL

SELECT --USER

dp.name, 'database_principal', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.database_principals dp

ON ep.class = 4

AND ep.name = 'MS_Description'

AND ep.major_id = dp.principal_id

UNION ALL

SELECT --PARTITION FUNCTION

pf.name, 'partition_function', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.partition_functions pf

ON ep.class = 21

AND ep.name = 'MS_Description'

AND ep.major_id = pf.function_id


UNION ALL

SELECT --REMOTE SERVICE BINDING

rsb.name, 'remote service binding', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.remote_service_bindings rsb

ON ep.class = 18

AND ep.name = 'MS_Description'

AND ep.major_id = rsb.remote_service_binding_id


UNION ALL

SELECT --Route

rt.name, 'route', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.routes rt

ON ep.class = 19

AND ep.name = 'MS_Description'

AND ep.major_id = rt.route_id


UNION ALL

SELECT --Service

sv.name COLLATE DATABASE_DEFAULT, 'service', ep.value

FROM sys.extended_properties ep

INNER JOIN sys.services sv

ON ep.class = 17

AND ep.name = 'MS_Description'

AND ep.major_id = sv.service_id

UNION ALL

SELECT -- 'CONTRACT'

svc.name, 'service_contract', ep.value

FROM sys.service_contracts svc

INNER JOIN sys.extended_properties ep

ON ep.class = 16

AND ep.name = 'MS_Description'

AND ep.major_id = svc.service_contract_id


UNION ALL

SELECT -- 'MESSAGE TYPE'

smt.name, 'message_type', ep.value

FROM sys.service_message_types smt

INNER JOIN sys.extended_properties ep

ON ep.class = 15

AND ep.name = 'MS_Description'

AND ep.major_id = smt.message_type_id

UNION ALL

SELECT -- 'assembly'

asy.name, 'assembly', ep.value

FROM sys.assemblies asy

INNER JOIN sys.extended_properties ep

ON ep.class = 5

AND ep.name = 'MS_Description'

AND ep.major_id = asy.assembly_id

/*UNION ALL SELECT --'CERTIFICATE'

cer.name,'certificate', value from sys.certificates cer

INNER JOIN sys.extended_properties ep ON class=?

AND ep.name = 'MS_Description' AND ep.major_id=cer.certificate_id

UNION ALL SELECT --'ASYMMETRIC KEY'

amk.name,'asymmetric_key', value SELECT * from sys.asymmetric_keys amk

INNER JOIN sys.extended_properties ep ON class=?

AND ep.name = 'MS_Description' AND ep.major_id=amk.asymmetric_key_id

SELECT --'SYMMETRIC KEY'

smk.name,'symmetric_key', value from sys.symmetric_keys smk

INNER JOIN sys.services sv ON class=?

AND ep.name = 'MS_Description' AND ep.major_id=smk.symmetric_key_id */

UNION ALL

SELECT -- 'PLAN GUIDE'

pg.name, 'plan_guide', ep.value

FROM sys.plan_guides pg

INNER JOIN sys.extended_properties ep

ON ep.class = 27

AND ep.name = 'MS_Description'

AND ep.major_id = pg.plan_guide_id

ORDER BY thing,path;


Get a detail list of all Database Object Extended Properties:

-- get extended properties of all objects in a DB


SELECT --objects

CASE

WHEN ob.parent_object_id > 0 --if it is a child object

THEN OBJECT_SCHEMA_NAME(ob.parent_object_id) --add the parent

+ '.' + OBJECT_NAME(ob.parent_object_id) + '.' + ob.name

ELSE OBJECT_SCHEMA_NAME(ob.object_id) + '.' + ob.name

END AS Object_Name

,ob.type_desc AS Object_Type

,COALESCE(ep.value, '') AS Extended_Property --display the property if there

FROM sys.objects ob

LEFT OUTER JOIN sys.extended_properties ep

ON ep.major_id = ob.object_id --class of 1 means Object or column

AND ep.class = 1 AND ep.minor_id = 0 AND ep.name='MS_Description'

WHERE ob.is_ms_shipped = 0 -- leave out all the system stuff

ORDER BY [Object_name] -- and order by the object name


Get a detail list of all Database Object and Column Extended Properties

-- get extended properties of all objects and columns in a DB

-- ordered by object name and column_id so the order matches table creation script



SELECT --objects AND columns

CASE WHEN parent_object_id > 0 --if it is a child object

THEN OBJECT_SCHEMA_NAME(parent_object_id)--add the parent

+ '.'+OBJECT_NAME(parent_object_id)+'.'+name

ELSE OBJECT_SCHEMA_NAME(object_id) + '.' + name END AS Object_Name

,type_desc As Object_Type

,COALESCE(value, '') AS Extended_Property --display the property if there

FROM

(

SELECT

ep.value

,ob.object_id

,ob.Parent_Object_id

,ob.name

,0

,type_desc

FROM sys.objects ob

LEFT OUTER JOIN sys.extended_properties ep

ON ep.major_id = ob.object_id --class= 1 means Object or column

AND ep.class = 1

AND ep.minor_id = 0

AND ep.name='MS_Description'

WHERE ob.is_ms_shipped = 0


UNION ALL --AND now we add the columns


SELECT

ep.value

,0

,col.Object_id

,col.name

,col.column_id

,'COLUMN'

FROM sys.columns col

LEFT OUTER JOIN sys.extended_properties ep

ON ep.major_id = col.object_id --1 means Object or column

AND ep.class = 1

AND ep.minor_id = column_id

AND ep.name='MS_Description'

WHERE ObjectPropertyEx(col.OBJECT_ID,'IsMSShipped') = 0

) AS ObjsAndCols(value, Object_id, Parent_Object_id,name, column_id, type_desc)

ORDER BY [Object_Name], column_id