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