MsSqlDbMng.DataBaseStructBuilder.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. 
  2. namespace Vit.Db.DbMng.MsSql
  3. {
  4. public partial class MsSqlDbMng
  5. {
  6. public static string DataBaseStructBuilder = @"
  7. -------------------
  8. --生成建库语句
  9. --1.生成 表字段、字段备注、默认值约束 、unique约束、primary key约束、索引的创建语句
  10. --2.生成触发器、函数、存储过程、视图的创建语句
  11. -- by lith on 2021-01-21 v2.3
  12. -------------------
  13. -- ------------------------------------------------------------------------------------
  14. -- 1.构建表头 备份时间、数据库版本、数据库名称
  15. select '
  16. -- (x.1)备份信息
  17. /* ';
  18. select '
  19. 备份时间 :',CONVERT(varchar(100), GETDATE(), 120);
  20. select '
  21. SqlServer版本 :',CONVERT(varchar(1000),@@version);
  22. --select '
  23. -- 数据库名称 :',(Select Name From Master..SysDataBases Where DbId=(Select Dbid From Master..SysProcesses Where Spid = @@spid)) as dbName;
  24. select '
  25. */
  26. ';
  27. -- ------------------------------------------------------------------------------------
  28. -- 2.生成 表字段、字段备注、默认值约束 、unique约束、primary key约束、索引的创建语句
  29. select ('
  30. /* (x.2)表 */
  31. ') comment;
  32. --(x.1)创建表用来存储数据库表的结构
  33. create table #Proc_S_TableStruct_ColInfo([col_id] int,[col_name] varchar(200),[col_typename] varchar(200),[col_len] int,[col_identity] int,[col_seed] int,[col_increment] int,[collation] varchar(200),[col_null] int,[col_DefaultValue] varchar(2000),[ConstraintName_DefaultValue] varchar(200),[ExtendedProperty] varchar(4000),[ConstraintName_PrimaryKey] varchar(200),[ConstraintName_Unique] varchar(200))
  34. create table #Proc_S_TableStruct_MShelpcolumns([col_name] varchar(200),[col_id] int,[col_typename] varchar(200),[col_len] int,[col_prec] varchar(200),[col_scale] varchar(200),[col_basetypename] varchar(200),[col_defname] varchar(200),[col_rulname] varchar(200),[col_null] int,[col_identity] int,[col_flags] int,[col_seed] int,[col_increment] int,[col_dridefname] varchar(200),[text] text ,[col_iscomputed] varchar(200),[col_text] varchar(200),[col_NotForRepl] int,[col_fulltext] int,[col_AnsiPad] int,[col_DOwner] int,[col_DName] varchar(200),[col_ROwner] int,[col_RName] varchar(200),[collation] varchar(200),[ColType] varchar(200),[column1] int ,[column2] int)
  35. create table #Proc_S_TableStruct_SqlCreateTb([id] int identity(1,1),sql varchar(700));
  36. select [Name] into #Proc_S_TableStruct_tbName from sysobjects where [type] = 'U' and [Name]!='dtproperties';
  37. --(x.2)获取所有的索引
  38. SELECT
  39. SCHEMA_NAME(t.schema_id) AS [架构名称],
  40. t.name AS [数据表名称],
  41. i.name AS [索引名称],
  42. i.type_desc as [索引类型],
  43. i.is_primary_key as [是否主键],
  44. i.is_unique as [是否唯一],
  45. i.is_unique_constraint as [是否外键],
  46. STUFF(REPLACE(REPLACE((
  47. SELECT QUOTENAME(c.name) + CASE WHEN ic.is_descending_key = 1 THEN ' DESC' ELSE '' END AS [data()]
  48. FROM sys.index_columns AS ic
  49. INNER JOIN sys.columns AS c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
  50. WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0
  51. ORDER BY ic.key_ordinal
  52. FOR XML PATH
  53. ), '<row>', ', '), '</row>', ''), 1, 2, '') AS [索引键列表],
  54. STUFF(REPLACE(REPLACE((
  55. SELECT QUOTENAME(c.name) AS [data()]
  56. FROM sys.index_columns AS ic
  57. INNER JOIN sys.columns AS c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
  58. WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 1
  59. ORDER BY ic.index_column_id
  60. FOR XML PATH
  61. ), '<row>', ', '), '</row>', ''), 1, 2, '') AS [包含列信息]
  62. -- ,u.user_seeks
  63. -- ,u.user_scans
  64. -- ,u.user_lookups
  65. -- ,u.user_updates
  66. into #Proc_S_TableStruct_Index
  67. FROM sys.tables AS t
  68. INNER JOIN sys.indexes AS i ON t.object_id = i.object_id
  69. -- LEFT JOIN sys.dm_db_index_usage_stats AS u ON i.object_id = u.object_id AND i.index_id = u.index_id and u.database_id= db_id()
  70. WHERE t.is_ms_shipped = 0
  71. AND i.type <> 0;
  72. --(x.3)循环处理各个表
  73. declare @tbName varchar(100);
  74. declare @tbCount int;
  75. declare @tbIndex int;
  76. set @tbCount=(select count(*) from #Proc_S_TableStruct_tbName);
  77. set @tbIndex=0;
  78. while 1=1
  79. begin
  80. --(x.x.1)
  81. set @tbIndex=@tbIndex+1;
  82. --(x.x.2)获取表信息
  83. set @tbName=( SELECT top 1 [Name] from #Proc_S_TableStruct_tbName)
  84. if @tbName is null
  85. break;
  86. delete #Proc_S_TableStruct_tbName where [Name]=@tbName;
  87. --(x.x.2.1) 获取字段基础信息
  88. insert into #Proc_S_TableStruct_MShelpcolumns exec sp_MShelpcolumns @tbName;
  89. select [col_id],[col_name],col_typename,col_len,col_identity,col_seed,col_increment,collation
  90. ,col_null,[text] col_DefaultValue,col_dridefname [ConstraintName_DefaultValue]
  91. into #Proc_S_TableStruct_Col
  92. from #Proc_S_TableStruct_MShelpcolumns;
  93. truncate table #Proc_S_TableStruct_MShelpcolumns;
  94. --(x.x.2.2) 获取字段的备注
  95. select objname [col_name],[value] [ExtendedProperty]
  96. into #Proc_S_TableStruct_Property
  97. from ::fn_listextendedproperty(null,N'user',N'dbo',N'table',@tbName,N'column',null)
  98. where 1=1;
  99. --(x.x.2.3)主码 和 唯一 约束 。 CONSTRAINT_TYPE: 'PRIMARY KEY' 和 'UNIQUE'
  100. select t1.COLUMN_NAME [col_name],t2.CONSTRAINT_TYPE ,t1.Constraint_Name
  101. into #Proc_S_TableStruct_Constraint
  102. from information_schema.key_column_usage t1
  103. left join information_schema.table_constraints t2 on t1.Constraint_Name=t2.Constraint_Name
  104. where t1.TABLE_NAME=@tbName;
  105. --(x.x.2.4) 合并最终结构数据
  106. insert into #Proc_S_TableStruct_ColInfo
  107. select c.*
  108. ,convert(varchar(8000) , p.[ExtendedProperty])
  109. ,conPrimary.Constraint_Name [ConstraintName_PrimaryKey]
  110. ,conUnique.Constraint_Name [ConstraintName_Unique]
  111. from #Proc_S_TableStruct_Col c
  112. left join #Proc_S_TableStruct_Property p on c.[col_name] Collate Database_Default =p.[col_name]
  113. left join #Proc_S_TableStruct_Constraint conPrimary on c.[col_name]=conPrimary.[col_name] and conPrimary.[CONSTRAINT_TYPE]='PRIMARY KEY'
  114. left join #Proc_S_TableStruct_Constraint conUnique on c.[col_name]=conUnique.[col_name] and conUnique.[CONSTRAINT_TYPE]='UNIQUE';
  115. --(x.x.2.5)清理数据
  116. drop table #Proc_S_TableStruct_Col;
  117. drop table #Proc_S_TableStruct_Property;
  118. drop table #Proc_S_TableStruct_Constraint;
  119. --(x.x.3)输出
  120. select ('
  121. /* ['+ CONVERT(varchar(10),@tbIndex)+'/'+ CONVERT(varchar(10),@tbCount) +']创建表 '+@tbName+' */
  122. ') comment;
  123. --(x.x.x.1)建表
  124. select ('
  125. /* 创建表字段 */') comment;
  126. insert into #Proc_S_TableStruct_SqlCreateTb(sql)
  127. select '
  128. create table [dbo].['+@tbName+'] ( ';
  129. insert into #Proc_S_TableStruct_SqlCreateTb(sql)
  130. select
  131. ' ['+[col_name]+'] ['+[col_typename]+']'
  132. -- [类型] (长度)
  133. +(case when(0!=charindex('char',col_typename)) then (case when [col_len]<=0 then '(MAX)' else ' ('+convert(varchar(100),[col_len])+')' end) else '' end)
  134. -- IDENTITY(2010,100)
  135. +(case when(1=col_identity) then ' IDENTITY('+convert(varchar(100),[col_seed]) +','+ convert(varchar(100),[col_increment]) +')' else '' end)
  136. -- COLLATE Chinese_PRC_CI
  137. +(case when(collation is not null) then ' COLLATE '+[collation] else '' end)
  138. -- NOT NULL
  139. +(case when(1=col_null) then ' NULL' else ' NOT NULL' end)
  140. +'
  141. ,'
  142. from #Proc_S_TableStruct_ColInfo;
  143. update #Proc_S_TableStruct_SqlCreateTb set sql=(isnull(left(sql,len(sql)-1),'')+'); ') where [ID]= (select max([ID]) from #Proc_S_TableStruct_SqlCreateTb);
  144. select sql from #Proc_S_TableStruct_SqlCreateTb;
  145. truncate table #Proc_S_TableStruct_SqlCreateTb;
  146. --(x.x.x.2)默认值约束
  147. select ('
  148. /* 默认值约束 */') comment;
  149. select ('
  150. alter table '+ quotename(@tbName)
  151. +' add constraint '+quotename(ConstraintName_DefaultValue)
  152. +' default'+col_DefaultValue
  153. +' for ' + quotename([col_name])
  154. +';') [sql]
  155. from #Proc_S_TableStruct_ColInfo
  156. where ConstraintName_DefaultValue is not null;
  157. --(x.x.x.3)unique约束 ALTER TABLE table_a ADD unique(aID);
  158. select ('
  159. /* unique约束 */') comment;
  160. select ('
  161. alter table '+ quotename(@tbName)
  162. +' add unique( '+quotename([col_name])+')'
  163. +';') [sql]
  164. from #Proc_S_TableStruct_ColInfo
  165. where ConstraintName_Unique is not null
  166. --(x.x.x.4)primary key约束
  167. --'ALTER TABLE ['+@tbName+'] ADD CONSTRAINT PK__'+@tbName+'_'+@colName+'__lit17032317 PRIMARY KEY CLUSTERED (['+@colName+']) '
  168. select ('
  169. /* primary key约束 */') comment;
  170. select('
  171. alter table '+ quotename(@tbName)
  172. +' add constraint '+quotename(ConstraintName_PrimaryKey)
  173. +' PRIMARY KEY CLUSTERED ('+quotename([col_name])+')'
  174. +';') [sql]
  175. from #Proc_S_TableStruct_ColInfo
  176. where ConstraintName_PrimaryKey is not null;
  177. --(x.x.x.5)索引
  178. -- CREATE NONCLUSTERED INDEX IX_Tileset_File ON dbo.Tileset_File
  179. -- (professionalTreeId, creator DESC,floorId)
  180. -- WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  181. select ('
  182. /* 索引 */') comment;
  183. select('
  184. CREATE NONCLUSTERED INDEX '+ quotename([索引名称])
  185. +' ON '+quotename([架构名称])+'.'+quotename([数据表名称])
  186. +'
  187. ('+[索引键列表]+')'
  188. +'
  189. WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];
  190. ') [sql]
  191. from #Proc_S_TableStruct_Index
  192. where [索引类型]='NONCLUSTERED' and [数据表名称]=@tbName;
  193. truncate table #Proc_S_TableStruct_ColInfo;
  194. end
  195. select '
  196. GO
  197. ';
  198. drop table #Proc_S_TableStruct_Index;
  199. drop table #Proc_S_TableStruct_tbName;
  200. drop table #Proc_S_TableStruct_MShelpcolumns;
  201. drop table #Proc_S_TableStruct_ColInfo;
  202. drop table #Proc_S_TableStruct_SqlCreateTb;
  203. -- ------------------------------------------------------------------------------------
  204. -- 3.生成触发器、函数、存储过程、视图的创建语句
  205. --(x.1)获取数据的语句
  206. declare @IDStart int;
  207. declare @IDNext int;
  208. --定义text 指针
  209. declare @ptrval BINARY(16)
  210. declare @sqlNext varchar(8000)
  211. SELECT Identity(int,1,1) [ID],
  212. o.xtype,
  213. (CASE o.xtype WHEN 'X' THEN '扩展存储过程' WHEN 'TR' THEN '触发器' WHEN 'PK' THEN '主键' WHEN 'F' THEN '外键' WHEN 'C' THEN '约束' WHEN 'V' THEN '视图' WHEN 'FN' THEN '函数-标量' WHEN 'IF' THEN '函数-内嵌' WHEN 'TF' THEN '函数-表值' ELSE '存储过程' END)
  214. AS [类型]
  215. , o.name AS [对象名]
  216. , o.crdate AS [创建时间]
  217. , o.refdate AS [更改时间]
  218. ,convert(text,c.[text]) AS [声明语句]
  219. into #tb
  220. FROM dbo.sysobjects o LEFT OUTER JOIN
  221. dbo.syscomments c ON o.id = c.id
  222. WHERE (o.xtype IN ('X', 'TR', 'C', 'V', 'F', 'IF', 'TF', 'FN', 'P', 'PK')) AND
  223. (OBJECTPROPERTY(o.id, N'IsMSShipped') = 0)
  224. --order BY o.xtype
  225. while(1=1)
  226. begin
  227. set @IDStart=null;
  228. select top 1 @IDStart=start.[ID], @IDNext=nex.[ID], @ptrval=TEXTPTR(start.[声明语句]),@sqlNext=convert(varchar(8000),nex.[声明语句])
  229. from #tb start,#tb nex where start.[ID]<nex.[ID] and start.[xtype]=nex.[xtype] and start.[对象名]=nex.[对象名];
  230. if( @IDStart is null) break;
  231. UPDATETEXT #tb.[声明语句] @ptrval NULL 0 @sqlNext;
  232. delete #tb where [id]=@IDNext;
  233. end
  234. --(x.3)触发器
  235. select ('
  236. /* (x.3)触发器 */
  237. ') comment;
  238. select [声明语句],'
  239. GO
  240. ' from #tb where xtype='TR';
  241. --(x.4)函数
  242. select ('
  243. /* (x.4)函数 */
  244. ') comment;
  245. select [声明语句],'
  246. GO
  247. ' from #tb where xtype='FN';
  248. select [声明语句] ,'
  249. GO
  250. ' from #tb where xtype='TF';
  251. --(x.5)存储过程
  252. select ('
  253. /* (x.5)存储过程 */
  254. ') comment;
  255. select [声明语句],'
  256. GO
  257. ' from #tb where xtype='P';
  258. --(x.6)视图 (考虑 依附关系)
  259. select ('
  260. /* (x.6)视图 */
  261. ') comment;
  262. select identity(int,1,1) [id],[对象名] [name], convert(smallint,null) SortCode into #tmp_Enty from #tb where xtype='V';
  263. SELECT distinct o.[name], p.[name] dependOn
  264. into #tmp_R
  265. FROM sysobjects o
  266. INNER JOIN sysdepends d ON d.id = o.id
  267. INNER JOIN sysobjects p ON d.depid = p.id and p.xtype='v' and exists(select 1 from #tmp_Enty where p.[name] = #tmp_Enty.[name] )
  268. where o.xtype='v' and exists(select 1 from #tmp_Enty where o.[name] = #tmp_Enty.[name] );
  269. declare @sc int;
  270. set @sc=1;
  271. while 1=1
  272. begin
  273. set @sc=@sc+1;
  274. update #tmp_Enty set SortCode=@sc from #tmp_Enty enty where SortCode is null
  275. and not exists(select 1 from #tmp_R r inner join #tmp_Enty parent on r.[dependOn]=parent.[name] where r.[name]=enty.[name] and parent.SortCode is null )
  276. if(0=@@ROWCOUNT)
  277. break;
  278. end
  279. update #tmp_Enty set SortCode=@sc+1 where SortCode is null;
  280. select [声明语句],'
  281. GO
  282. ' from #tb inner join #tmp_Enty on #tb.对象名=#tmp_Enty.[name] order by SortCode;
  283. drop table #tmp_Enty;
  284. drop table #tmp_R;
  285. drop table #tb;
  286. ";
  287. }
  288. }