ドキュメントに拡張プロパティを使用すること、またはテーブルにタグを付ける簡単な方法を持つことは印象的な考えですが、ドキュメントのスニペットを設定するには、次のようなものを実行する必要があります。
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 の拡張プロパティを自動ドキュメント化に使用する簡単で便利な方法はありますか? いいえ、自分で書かない限り
以下に、私の回答の 2 番目の部分を示します。1 つの投稿が 30.000 文字に制限されているため、回答を分割する必要がありました。答えは1つの投稿にまとめなければならないというルールがあるようです。それで、誰かが答えの2番目の部分を質問に入れました。したがって、興味がある場合は、最初に回答を読んでから、ここに戻って 2 番目の部分をご覧ください。ご不便おかけしてすみません
これは、ステップ 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