-2

为文档使用扩展属性是一个惊人的想法,或者有一种简单的方法来标记您的表,但是要设置一个文档片段,您必须执行以下操作:

EXECUTE sp_addextendedproperty 
    @name = N'MS_Description', 
    @value = N'custom description text', 
    @level0type = N'SCHEMA', @level0name = N'SchemaName', 
    @level1type = N'TABLE', @level1name = N'TableName';

或执行几次鼠标点击,直到您可以输入您的描述。

如果您想浏览您的文档,您可以使用一些选择,例如

select
    SysTbls.name as [Table Name],
    ExtProp.name as [Extended Property Name],
    ExtProp.value as [Extended Property],
    SysObj.create_date as [Table Create Date],
    SysObj.modify_date as [Table Modify Date],
    ExtProp.minor_id 
from 
    sys.tables SysTbls
left join 
    sys.extended_properties ExtProp on ExtProp.major_id = SysTbls.object_id
left join 
    sys.objects SysObj on SysTbls.object_id = SysObj.object_id
where 
    ExtProp.class = 1 --Object or column
    and SysTbls.name is not null;

或者您可以使用 Red-Gate Documentation 之类的工具,但此工具似乎仅限于扩展属性“MS_Description”。

因此,当您必须记录具有数十个表、数百列和数十个过程/视图等的多个数据库时,如果您想查找一些扩展属性,例如“票号”或“需要数据保护”,则需要一个加速工作的工具。重复标题中的问题:是否有一种简单方便的方法可以使用 SQL Server 扩展属性进行自动文档?不,除非你自己写


您可以在下面找到我答案的第二部分。我不得不拆分答案,因为一篇帖子限制为 30.000 个字符。似乎,有一条规则,答案必须在一篇文章中。所以有人把答案的第二部分放在问题中。因此,如果您有兴趣,请先阅读答案,然后返回此处查看第二部分。带来不便敬请谅解


这是步骤 3 中的过程代码


create procedure [dbo].[usp_make_extended_properties_statements] @source_table nvarchar(100) , @refresh_documentation_table bit = 1
as
begin
set nocount on
--
-- =============================================
-- Name       : usp_make_extended_properties_statements
-- Description: 
-- it compares dbo.documentation with the values from the source_table and creates insert/update/delete-Statements for extended properties
-- Step 1) create the source_table : e.g.: select * into table_1 from dbo.documentation
-- you can restrict on lines from interest e.g. select * into only_clients_tables from dbo.documentation where Object_Name like '%client%'

-- Step 2)  edit your source_table
--          e.g. update only_clients_tables 
--               set Extended_Property = 'dataprotect' and Extended_Property_Value = 'true'
--               where Column_or_Index_Name in ('name', 'surname' ,'street', 'zip' , 'town')
--          or use a tool, e.g. Aquadata-DataEdit, where you can handle it like a excel-Sheet
--          or any other tool you favorize
-- it is possible to  insert, update und delete extended properties with the source-Table
-- to delete extended properties empty the columns Extended_Property and Extended_Property_Value (set to value <null> )

-- Step 3) exec usp_make_extended_properties_statements 'yourDatabase.yourSchema.yourSourceTableName'
-- this will result in bunch of statements, copy them to a query-window and execute them

-- Step 4) exec dbo.usp_fill_doc_table  
-- =============================================

declare @sql nvarchar(4000)
        ,@dbname nvarchar(100)
        ,@schemaname nvarchar(100)
        ,@tablename nvarchar(255)


        SET @dbname     = PARSENAME(@source_table, 3);
        SET @schemaname = PARSENAME(@source_table, 2);
        SET @tablename  = PARSENAME(@source_table, 1);

        select @dbname ,@schemaname,@tablename


        if ( @tablename is null or @schemaname is null or @dbname is null )
        begin
            print 'table '+@source_table+' doesnt exist or Parameter not given in format DBname.Schemaname.Tablenname ' + CHAR(13) + 'which was created by: select * into source_table from dbo.documentation' + CHAR(13) + ' for editing (insert/update/delete)' + CHAR(13) + ' after editing:  exec usp_make_extended_properties_statements ''source_table''
            '
            return 0
        end

        set @sql = '
        select count(1) from '+@dbname+'.sys.columns c join '+@dbname+'.sys.tables t on t.object_id = c.object_id where t.name = '''+@tablename+'''
        and c.name in (N''Object_Type'', N''Database_Name'', N''Schema_Name'', N''Object_Name'', N''Column_or_Index_Name'', N''Extended_Property'', N''Extended_Property_Value'')
        '

        create table #soll (
        Object_Type varchar(60) NULL,
        Database_Name varchar(50) NULL,
        Schema_Name varchar(30) NOT NULL,
        Object_Name varchar(128) NOT NULL,
        Column_or_Index_Name varchar(100) NULL,
        Extended_Property varchar(100) NULL,
        Extended_Property_Value varchar(5000) NULL
         )
        --declare @sql nvarchar(4000), @source_table nvarchar(100) = 'worker.cjonas.ep'
        set @sql = '
        select Object_Type, Database_Name, Schema_Name, Object_Name, Column_or_Index_Name, Extended_Property, Extended_Property_Value
        from '+@source_table+' where Object_type is not null'

        begin try
            insert into #soll
                (
                    Object_Type,
                    Database_Name,
                    Schema_Name,
                    Object_Name,
                    Column_or_Index_Name,
                    Extended_Property,
                    Extended_Property_Value
                )
            EXEC SP_EXECUTESQL @sql
        end try
        begin catch
                select @source_table+' must have columns Object_Type, Database_Name, Schema_Name, Object_Name, Column_or_Index_Name, Extended_Property, Extended_Property_Value '+error_message()

        end catch

        --replace empty String with <null>
        update #soll set Column_or_Index_Name = null where Column_or_Index_Name = ''


        -- retrieve actual state:
        if ( @refresh_documentation_table  = 1)  exec dbo.usp_fill_doc_table;

        select distinct d.Object_Type,
                d.Database_Name,
                d.Schema_Name,
                d.Object_Name,
                d.Column_or_Index_Name,
                d.Extended_Property,
                d.Extended_Property_Value 
        into #ist
        from dbo.documentation d join #soll s on d.Database_Name = s.Database_Name and d.Schema_name = s.Schema_name and d.Object_name = s.Object_name
        where d.Object_Type is not null

        
        --------------------------------------
        -- create insert or update-Statements 


     declare 
     @Object_Type sysname, @Database_Name sysname, @Schema_Name sysname, @Object_Name sysname,@level1type sysname,
     @Extended_Property nvarchar(1000),@Extended_Property_Value nvarchar(1000), 
     @Column_or_Index_Name sysname = null

      --select * from #ist; select * from #soll 
     -- 
      ----------------------------------------------------------------
     ---- add or  update extended_properties
     ----------------------------------------------------------------
          select Object_Type, Database_Name, Schema_Name, Object_Name, Column_or_Index_Name, Extended_Property, Extended_Property_Value 
          from #soll where Extended_Property is not null
          except
          select Object_Type, Database_Name, Schema_Name, Object_Name, Column_or_Index_Name, Extended_Property, Extended_Property_Value
          from #ist  where Extended_Property is not null;


     declare db_cursor cursor local fast_forward for
          select Object_Type, Database_Name, Schema_Name, Object_Name, Column_or_Index_Name, Extended_Property, Extended_Property_Value 
          from #soll where Extended_Property is not null and Extended_Property <> 'no extended property'
          except
          select Object_Type, Database_Name, Schema_Name, Object_Name, Column_or_Index_Name, Extended_Property, Extended_Property_Value
          from #ist  where Extended_Property is not null and Extended_Property <> 'no extended property';
     open db_cursor;
     fetch next from db_cursor into @Object_Type , @Database_Name , @Schema_Name , @Object_Name, @Column_or_Index_Name , @Extended_Property ,@Extended_Property_Value 

     
    while @@FETCH_STATUS = 0  
     begin

         IF DB_ID(@Database_Name) IS NULL
        BEGIN
            RAISERROR ('Unknown Database Name %s', 11, 1, @Database_Name);
            return -1;
        end

        

    -- Trim @Object_Type only allowed values
    -- for @level1type : Aggregate, Default, Function, Logical File Name, PROCEDURE, Queue, Rule, Sequence, Synonym, Table, TABLE_TYPE, Type, View, XML Schema Collection and NULL
    -- for @level2type : COLUMN, CONSTRAINT, EVENT NOTIFICATION, INDEX, PARAMETER, TRIGGER und NULL
     
     select @Object_Type = 
        case 
            when @Object_Type like '%procedure'         then 'PROCEDURE'
            when @Object_Type like '%index'             then 'INDEX'
            when @Object_Type like '%function'          then 'FUNCTION'
            when @Object_Type in   ('foreign_key','check','primary_key','unique') then 'CONSTRAINT'
            when @Object_Type =    'sequence_object'    then 'SEQUENCE'
            else @Object_Type
        end

    
      ---------  
      IF @Column_or_Index_Name IS null
      begin
        SET @sql = CONCAT('use ', @Database_Name, CHAR(13) + CHAR(10)
                        , 'go', CHAR(13) + CHAR(10)
                        , 'if not exists (select 1 from sys.extended_properties AS ep WHERE ep.major_id = OBJECT_ID(''',@Schema_Name ,'.', @Object_Name,''') AND ep.minor_id = 0 AND ep.name = ''', @Extended_Property,''')'
                        , char(13) +  char(10) 
                        , 'begin'
                        , char(13) +  char(10) 
                        , 'exec ', @Database_Name,'.sys.sp_addextendedproperty    @name = ''', @Extended_Property,''', @value =''', @Extended_Property_value,''', @level0type = N''SCHEMA'', @level0name = ''', @Schema_Name,''', @level1type = ''', @Object_Type,''',  @level1name = ''', @Object_Name,''''
                        , char(13) +  char(10)
                        , 'end'
                        , char(13) +  char(10) 
                        , 'else begin'
                        , char(13) +  char(10)
                        , 'exec ', @Database_Name,'.sys.sp_updateextendedproperty @name = ''', @Extended_Property,''', @value = ''', @Extended_Property_value,''', @level0type = N''SCHEMA'', @level0name = ''', @Schema_Name,''', @level1type = ''', @Object_Type,''',  @level1name = ''', @Object_Name,''''
                        , char(13) +  char(10)
                        ,'end;'
                        , char(13) +  char(10)
                         );
    end  -- if
    else    
    begin

    --- table or view:
    set @level1type = (
    select distinct Object_Type as level1type 
    from dbo.documentation d 
    where Object_Type in ( 'table','view') and Object_Name= @Object_Name and Schema_Name = @Schema_Name and Database_Name = @Database_Name
    )

    select  @level1type as  level1type
    select *
    from sys.objects o 
    join sys.schemas s on s.schema_id = o.schema_id
    where o.name = @Object_Name and s.name = @Schema_Name
    --- Spalte oder Index:
        set @sql = concat('use ', @Database_Name, char(13) + char(10)
                        , 'go'
                        , char(13) + char(10)
                        , 'if not exists '
                        , char(13) + char(10)
                        , '(select 1 from SYS.columns AS c INNER JOIN sys.extended_properties as ep ON ep.major_id = c.object_id AND ep.minor_id = c.column_id and ep.name = ''',@Extended_Property,'''',char(13) + char(10) 
                        , 'where c.object_id =  OBJECT_ID(''',@Schema_Name ,'.', @Object_Name,''') AND c.name = ''',@Column_or_Index_Name, ''')'
                        , char(13) + char(10) 
                        , 'and not exists ',char(13) + char(10) 
                        , '(SELECT 1 FROM sys.extended_properties ep join sys.indexes i ON ep.major_id =  i.object_id AND ep.name = ''',@Extended_Property,'''',char(13) + char(10) 
                        , 'where ep.major_id =  OBJECT_ID(''',@Schema_Name ,'.', @Object_Name,''') AND i.name = ''',@Column_or_Index_Name, ''')'
                        , char(13) + char(10)
                        , 'begin '
                        , char(13) + char(10)
                        , 'exec ', @Database_Name,'.sys.sp_addextendedproperty    @name = ''', @Extended_Property,''', @value = ''', @Extended_Property_value,''', @level0type = N''SCHEMA'', @level0name = ''', @Schema_Name,''', @level1type = ''',@level1type,''',  @level1name = ''', @Object_Name,''', @level2type = ''', @Object_Type,''',  @level2name = ''',@Column_or_Index_Name,''''
                        , char(13) + char(10)
                        , 'end'
                        , char(13) + char(10)
                        , 'else begin '
                        , char(13) + char(10)
                        , 'exec ', @Database_Name,'.sys.sp_updateextendedproperty @name = ''', @Extended_Property,''', @value = ''', @Extended_Property_value,''', @level0type = N''SCHEMA'', @level0name = ''', @Schema_Name,''', @level1type = ''',@level1type,''',  @level1name = ''', @Object_Name,''', @level2type = ''', @Object_Type,''',  @level2name = ''', @Column_or_Index_Name,''''
                        , char(13) + char(10)
                        , 'end ;'
                        , char(13) + char(10)
                         )
        ;
      end  ---ifelse
        
            print '-- Insert or update extended properties:'
            print @sql
       --EXEC SP_EXECUTESQL @sql

         fetch next from db_cursor into @Object_Type , @Database_Name , @Schema_Name , @Object_Name, @Column_or_Index_Name , @Extended_Property ,@Extended_Property_Value ;
     end;

     close db_cursor;
     deallocate db_cursor;


     -- --------------------
   select
        i.Object_Type,
        i.Database_Name,
        i.Schema_Name,
        i.Object_Name,
        i.Column_or_Index_Name,
        i.Extended_Property
      from #soll     s
     right join #ist i
        on i.Object_Type                       = s.Object_Type
       and i.Database_Name                     = s.Database_Name
       and i.Schema_Name                       = s.Schema_Name
       and i.Object_Name                       = s.Object_Name
       and isnull(i.Extended_Property, 'null')   = isnull(s.Extended_Property, 'null')
       and isnull(i.Column_or_Index_Name,'null') = isnull(s.Column_or_Index_Name,'null')
     where s.extended_property is null
       and i.Object_type is not null and i.extended_property <> 'no extended property'


     ----------------------------------------------------------------
     ---- deleted extended_properties
     ----------------------------------------------------------------
     declare db_cursor2 cursor local fast_forward for
        select
        i.Object_Type,
        i.Database_Name,
        i.Schema_Name,
        i.Object_Name,
        i.Column_or_Index_Name,
        i.Extended_Property
      from #soll     s
     right join #ist i
        on i.Object_Type                       = s.Object_Type
       and i.Database_Name                     = s.Database_Name
       and i.Schema_Name                       = s.Schema_Name
       and i.Object_Name                       = s.Object_Name
       and isnull(i.Extended_Property, 'null')   = isnull(s.Extended_Property, 'null')
       and isnull(i.Column_or_Index_Name,'null') = isnull(s.Column_or_Index_Name,'null')
     where s.extended_property is null
       and i.Object_type is not null and i.extended_property <> 'no extended property'

     open db_cursor2;
     fetch next from db_cursor2 into @Object_Type , @Database_Name , @Schema_Name , @Object_Name, @Column_or_Index_Name , @Extended_Property

     while @@FETCH_STATUS = 0  
     begin

         IF DB_ID(@Database_Name) IS NULL
        BEGIN
            RAISERROR ('Unknow Databasename %s', 11, 1, @Database_Name);
            return -1;
        end  
    -- Trim @Object_Type only allowed values
    -- for @level1type : Aggregate, Default, Function, Logical File Name, PROCEDURE, Queue, Rule, Sequence, Synonym, Table, TABLE_TYPE, Type, View, XML Schema Collection und NULL
    -- for @level2type : COLUMN, CONSTRAINT, EVENT NOTIFICATION, INDEX, PARAMETER, TRIGGER und NULL
     
     select @Object_Type = 
        case 
            when @Object_Type like '%procedure'         then 'PROCEDURE'
            when @Object_Type like '%index'             then 'INDEX'
            when @Object_Type like '%function'          then 'FUNCTION'
            when @Object_Type in   ('foreign_key','check','primary_key','unique') then 'CONSTRAINT'
            when @Object_Type =    'sequence_object'    then 'SEQUENCE'
            else @Object_Type
        end


        if @Column_or_Index_Name is null
        begin
        set @sql =  concat('use ', @Database_Name
                        ,  char(13) +  char(10)
                        , 'go'
                        ,  char(13) +  char(10)
                        , 'if exists (select 1 from sys.extended_properties AS ep '
                        , 'WHERE ep.major_id =  OBJECT_ID(''',@Schema_Name ,'.', @Object_Name,''') AND ep.minor_id = 0 AND ep.name = ''',@Extended_Property,''')'
                        ,  char(13) + char(10) 
                        , 'EXEC ', @Database_Name,'.sys.sp_dropextendedproperty  @name = ''', @Extended_Property,''', @level0type = N''SCHEMA'', @level0name = ''', @Schema_Name,''', @level1type = ''', @Object_Type,''',  @level1name = ''', @Object_Name,''''
                        ,';'
                        ,  char(13) + char(10)
                         )
           
        end
        else
        begin

        --- table or view:
        set @level1type = (
        select distinct Object_Type as level1type 
        from dbo.documentation d 
        where Object_Type in ( 'table','view') and Object_Name= @Object_Name and Schema_Name = @Schema_Name and Database_Name = @Database_Name
        )
        --- column or Index:
        set @sql =  concat('USE ', @Database_Name, char(13) + char(10)
                        , 'go', char(13) + char(10)
                        , 'IF EXISTS' 
                        , char(13) + char(10)
                        ,'(SELECT 1 FROM SYS.columns AS c INNER JOIN sys.extended_properties AS ep ON ep.major_id = c.object_id AND ep.minor_id = c.column_id AND ep.name = ''',@Extended_Property,''''
                        ,char(13) + char(10) 
                        , 'WHERE c.object_id =  OBJECT_ID(''',@Schema_Name ,'.', @Object_Name,''') AND c.name = ''',@Column_or_Index_Name, ''')'
                        ,char(13) + char(10) 
                        , 'or exists '
                        ,char(13) + char(10) 
                        ,'(SELECT 1 FROM sys.extended_properties ep join sys.indexes i ON ep.major_id =  i.object_id AND ep.name = ''',@Extended_Property,''''
                        ,char(13) + char(10) 
                        , 'WHERE ep.major_id =  OBJECT_ID(''',@Schema_Name ,'.', @Object_Name,''') AND i.name = ''',@Column_or_Index_Name, ''')'
                        , char(13) + char(10)
                        , 'EXEC ', @Database_Name,'.sys.sp_dropextendedproperty  @name = ''', @Extended_Property,''', @level0type = N''SCHEMA'', @level0name = ''', @Schema_Name,''', @level1type = ''',@level1type,''',  @level1name = ''', @Object_Name,''', @level2type = ''', @Object_Type,''',  @level2name = ''', @Column_or_Index_Name,'''' 
                        ,';'
                        , char(13) + char(10)
                         )
           
        end
        print '-- Delete extended properties:'
        print @sql
        --EXEC SP_EXECUTESQL @sql
        fetch next from db_cursor2 into @Object_Type , @Database_Name , @Schema_Name , @Object_Name, @Column_or_Index_Name , @Extended_Property ;
     end;
       
     close db_cursor2;
     deallocate db_cursor2;

     --- actualize Documentation-table:
     --- only when you have uncommented every: "--EXEC SP_EXECUTESQL @sql"
     --- then uncomment following line, too:
     --  if ( @refresh_documentation_table  = 1)  exec dbo.usp_fill_doc_table;

end


4

1 回答 1

0

这个工具(我必须自己写)包括

  1. 表,其中包含所有扩展属性(以及一些附加信息)
  2. 填写此表的程序,该表每天运行或在需要时运行
  3. 过程,一步轻松设置一大堆扩展属性
  4. 可选:用于搜索和浏览文档的 SSRS 报告-表格

这些是活动部件:

  1. 存放文件的表格
create table [dbo].[documentation]
(
    [Object_Type] [varchar](60) null,
    [Database_Name] [varchar](50) null,
    [Schema_Name] [varchar](30) not null,
    [Object_Name] [varchar](128) not null,
    [Column_or_Index_Name] [varchar](256) null,
    [Extended_Property] [varchar](100) null,
    [Extended_Property_Value] [varchar](5000) null,
    [Data_Type] [sysname] null,
    [Column_Length] [varchar](22) null,
    [Column_is_Nullable] [varchar](3) null,
    [Create_Date] [datetime2](0) null,
    [Modify_Date] [datetime2](0) null,
    [Column_Number] [smallint] null
)
  1. 填写文档表的程序:
CREATE PROCEDURE [dbo].[usp_fill_doc_table] 
AS
BEGIN
    SET NOCOUNT ON;

-- =============================================
-- Name       : usp_fill_doc_table
-- Description: scans all databases ( except master,tempdb etc. ) for extended properties and fills table dbo.documentation
--              all objects, whether they do have a extended property or not are listed              
-- =============================================

declare @sql1 nvarchar(2000)
declare @sql2 nvarchar(2000)
declare @sql3 nvarchar(2000)

truncate table dbo.documentation

-- objects with extended_properties

        set @sql1  ='
use ?
if (  db_name(db_id()) not in (''master'',''tempdb'',''model'',''msdb'',''SSISDB'')  )
begin
insert into dbo.documentation            
select
case when SC.name is null then lower(replace(replace(replace(SO.type_desc,''USER_'',''''),''SQL_'',''''),''_CONSTRAINT'','''')) else ''column'' end  o1,
db_name() db,
SS.name sn,
SO.name so,
SC.name sc,
EP.name epn,
try_cast(EP.value as varchar(5000)) ep,
ST.name stn,
case when ST.name in (''nvarchar'', ''nchar'')
then convert(varchar(10), ( SC.max_length / 2 ))
when ST.name in (''char'', ''varchar'')
then convert(varchar(10), SC.max_length)
else null
end epv,
case when SC.is_nullable = 0 then ''No'' when SC.is_nullable = 1 then ''Yes'' else null end n,
case when SC.name is null then SO.create_date else null end c,
case when SC.name is null then SO.modify_date else null end m,
isnull(SC.column_id,0) ci
from sys.objects SO
join sys.schemas SS
on SS.schema_id = SO.schema_id
left join sys.extended_properties EP
on EP.major_id = SO.object_id
left join sys.columns SC
on EP.major_id = SC.object_id
and EP.minor_id = SC.column_id
left join sys.types ST
on SC.user_type_id = ST.user_type_id and SC.system_type_id = ST.system_type_id
where SO.is_ms_shipped = 0 and ep.class_desc = ''OBJECT_OR_COLUMN''
  union all
select distinct
lower(EP.class_desc) o1,
db_name() db,
SS.name sn,
SO.name so,
i.name sc,
EP.name epn,
try_cast(EP.value as varchar(5000)) ep,
null stn,
null epv,
null n,
null c,
null m,
0 ci
from sys.objects SO
join sys.schemas SS
on SS.schema_id = SO.schema_id
left join sys.extended_properties EP
on EP.major_id = SO.object_id
left join sys.indexes i on i.object_id = SO.object_id and i.index_id = ep.minor_id
where SO.is_ms_shipped = 0 and ep.class_desc <> ''OBJECT_OR_COLUMN'' 
end
'
        ;

        -- objects without extended_properties, but with columns/index etc
       
        set @sql2  ='
use ?
if (  db_name(db_id()) not in (''master'',''tempdb'',''model'',''msdb'',''SSISDB'')  )
begin   
insert into dbo.documentation
select
    case when SC.name is null then lower(replace(replace(replace(SO.type_desc,''USER_'',''''),''SQL_'',''''),''_CONSTRAINT'','''')) else ''column'' end  o1,
    db_name() db,
    SS.name sn,
    SO.name so,
    SC.name sc,
    ''no extended property'' epn,
    try_cast(EP.value as varchar(5000)) ep,
    ST.name stn,
    case when ST.name in (''nvarchar'', ''nchar'')
        then convert(varchar(10), ( SC.max_length / 2 ))
        when ST.name in (''char'', ''varchar'')
        then convert(varchar(10), SC.max_length)
        else null
    end epv,
    case when SC.is_nullable = 0 then ''No'' when SC.is_nullable = 1 then ''Yes'' else null end n,
    case when SC.name is null then SO.create_date else null end c,
    case when SC.name is null then SO.modify_date else null end m,
    isnull(SC.column_id,0) ci
from sys.objects                  SO
join sys.schemas                  SS
    on SS.schema_id = SO.schema_id
join sys.columns             SC
on SO.object_id     = SC.object_id
left join sys.extended_properties EP
    on EP.major_id     = SO.object_id
    and EP.minor_id     = SC.column_id
left join sys.types               ST
    on SC.user_type_id = ST.user_type_id and SC.system_type_id = ST.system_type_id
    where SO.is_ms_shipped = 0 and EP.minor_id is null and SO.type <>''IF''
end
'
;

        -- Objects without extended_properties and without Columns
        set @sql3  ='
use ?
if (  db_name(db_id()) not in (''master'',''tempdb'',''model'',''msdb'',''SSISDB'')  )
begin   
insert into dbo.documentation
select
    case when i.name is null then lower(replace(replace(replace(SO.type_desc,''USER_'',''''),''SQL_'',''''),''_CONSTRAINT'','''')) 
    else case when i.is_unique =1 then ''unique '' else '''' end  
    + lower(i.type_desc) + '' index'' end o1,
    db_name() db,
    SS.name sn,
    SO.name so,
    i.name sc,
    ''no extended property'' epn,
    null as epv,
    null as dt,
    null as cl,
    null as cin,
    SO.create_date,
    SO.modify_date,
    0
from sys.objects SO
join sys.schemas SS
    on SS.schema_id = SO.schema_id
left join sys.indexes i on SO.object_id = i.object_id
 where SO.is_ms_shipped = 0
insert into dbo.documentation
select
    lower(replace(replace(replace(SO.type_desc,''USER_'',''''),''SQL_'',''''),''_CONSTRAINT'','''')) o1,
    db_name() db,
    SS.name sn,
    SO.name so,
    null,
    ''no extended property'' epn,
    null as epv,
    null as dt,
    null as cl,
    null as cin,
    SO.create_date,
    SO.modify_date,
    0
from sys.objects SO
join sys.schemas SS
    on SS.schema_id = SO.schema_id
 where SO.is_ms_shipped = 0
end
'
;

    exec sp_msforeachdb @command1 = @sql1,@command2 = @sql2 ,@command3 = @sql3 

      --- some special objects like _ST_2610A626_00000003_00005585 are not interesting:
    delete from dbo.documentation where Object_type is null


        --- beautify the result:

        -- remove double

        ;with dubletten as (
                select count(1) as z,Object_Type,Database_Name,Schema_Name,Object_Name,Column_or_Index_Name,Extended_Property
                from dbo.documentation  
                group by Object_Type,Database_Name,Schema_Name,Object_Name,Column_or_Index_Name,Extended_Property
                having count(1) >1)
        select distinct a.* into #dubletten
        from dbo.documentation a
          join dubletten                doppelte
            on a.Object_Name          = doppelte.Object_Name
           and a.Schema_Name          = doppelte.Schema_Name
           and a.Database_Name        = doppelte.Database_Name
           and a.Object_Type          = doppelte.Object_Type
           and a.Extended_Property    = doppelte.Extended_Property


        delete from dbo.documentation
        from dbo.documentation a
          join #dubletten                doppelte
            on a.Object_Name          = doppelte.Object_Name
           and a.Schema_Name          = doppelte.Schema_Name
           and a.Database_Name        = doppelte.Database_Name
           and a.Object_Type          = doppelte.Object_Type
           and a.Extended_Property    = doppelte.Extended_Property

        insert into dbo.documentation
        select * from #dubletten d


        --- one object shouldn't be listed twice with a) 'no extended property' and with b) 'MS_Description'
        --- a) double-listed objects with a extended property set

    ;with alle_mehrfachen_objekte as (
        select count(1) as z,Object_Type,Database_Name,Schema_Name,Object_Name 
        from dbo.documentation where Column_or_Index_Name is null  
        group by Object_Type,Database_Name,Schema_Name,Object_Name
        having count(1) >1)
    delete from dbo.documentation
      from dbo.documentation a
      join alle_mehrfachen_objekte                doppelte
        on a.Object_Name          = doppelte.Object_Name
       and a.Schema_Name          = doppelte.Schema_Name
       and a.Database_Name        = doppelte.Database_Name
       and a.Object_Type          = doppelte.Object_Type
     where a.Column_or_Index_Name is null
       and a.Extended_Property = 'no extended property'
       and ( a.Extended_Property_Value is null or a.Extended_Property_Value = '');

        --- b) double-listed objects which are columns, with a extended property set
    ;with alle_mehrfachen_objekte as (
        select count(1) as z,Database_Name,Schema_Name,Object_Name,Column_or_Index_Name 
        from dbo.documentation 
        where Column_or_Index_Name is not null and Object_Type = 'column' 
        group by Database_Name,Schema_Name,Object_Name,Column_or_Index_Name
        having count(1) >1)
    delete from dbo.documentation  
      from dbo.documentation a
      join alle_mehrfachen_objekte                doppelte
        on a.Object_Name          = doppelte.Object_Name
       and a.Schema_Name          = doppelte.Schema_Name
       and a.Database_Name        = doppelte.Database_Name
       and a.Column_or_Index_Name          = doppelte.Column_or_Index_Name
     where a.Column_or_Index_Name is not null
        and a.Object_Type = 'column'
       and a.Extended_Property = 'no extended property'
       and ( a.Extended_Property_Value is null or a.Extended_Property_Value = '');

        --- b) double-listed objects which are not columns ( but e.g. index ), with a extended property set
    ;with alle_mehrfachen_objekte as (
        select count(1) as z,Database_Name,Schema_Name,Object_Name,Column_or_Index_Name 
        from dbo.documentation 
        where Column_or_Index_Name is not null and Object_Type <> 'column' 
        group by Database_Name,Schema_Name,Object_Name,Column_or_Index_Name
        having count(1) >1)
    delete from dbo.documentation  
      from dbo.documentation a
      join alle_mehrfachen_objekte                doppelte
        on a.Object_Name          = doppelte.Object_Name
       and a.Schema_Name          = doppelte.Schema_Name
       and a.Database_Name        = doppelte.Database_Name
       and a.Column_or_Index_Name          = doppelte.Column_or_Index_Name
     where a.Column_or_Index_Name is not null
        and a.Object_Type <> 'column'
       and a.Extended_Property = 'no extended property'
       and ( a.Extended_Property_Value is null or a.Extended_Property_Value = '');
end
  1. 基于表作为输入创建所有扩展属性语句的过程
    1. create the source_table : e.g.: select * into table_1 from dbo.documentation
     - you can restrict on lines from interest e.g. select * into only_clients_tables from dbo.documentation where Object_Name like '%client%'
    2. edit your source_table
     - e.g. update only_clients_tables 
              set Extended_Property = 'dataprotect' and Extended_Property_Value = 'true'
             where Column_or_Index_Name in ('name', 'surname' ,'street', 'zip' , 'town')
        - or use a tool, e.g. Aquadata-DataEdit, where you can handle it like a excel-Sheet
        - or any other tool you favorize
        - it is possible to  insert, update und delete extended properties with the source-Table
        - to delete extended properties empty the columns Extended_Property and Extended_Property_Value (set to value <null> )

    3. exec usp_make_extended_properties_statements 'yourDatabase.yourSchema.yourSourceTableName'
        - this will result in bunch of statements, copy them to a query-window and execute them

    4. exec dbo.usp_fill_doc_table 
  1. SSRS-报告搜索或浏览文档-表格

该报告可能如下所示: 用于搜索和浏览的报告 dbo.documentation

于 2022-01-04T15:40:41.257 回答