各位博友大家好

先前一段时间接手一个项目,我负责后台需求的接口开发。
但是客户只提供了测试数据库服务器和原型设计,缺少相关文档,就接口开发的话,我相对而言要确定的有两点:一个是需求确认、另一个就是数据库表的确认了。需求可以在原型上体现,但是数据库表关系的话只是开数据库表不是很直观,所以参照之前公司的表结构模板写了一个导出表结构的小程序,现在和大家分享一下。
目前支持sqlserver2012 导出序列、函数、存储过程、表结构
mysql暂时支持导出表结构

Demo源代码下载地址:

代码上不好的地方还望同仁们指教指教,有什么不明白的也可以直接留言问我的

创建测试库、表、存储过程、函数、序列(sqlserver2012以上),这个我就不说明了,大家自建一个就好,如在这步有问题,请参照有关知识点进行创建,谢谢。

sqlserver2012 – 序列

/// <summary>
        /// 取得所有序列
        /// </summary>
        public static DataTable GetAllSequences(out string strDBName)
        {
            DataTable dtResult = new DataTable();
            DBHelper dbHelper = new DBHelper();
            StringBuilder strSql = new StringBuilder("");
            strSql.AppendFormat("SELECT 'IF NOT EXISTS(SELECT * FROM sys.sequences WHERE name=N'''+NAME+''') {0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" CREATE SEQUENCE '+NAME+' AS bigint {0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" START WITH '+CONVERT(VARCHAR,START_VALUE)+'{0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" INCREMENT BY '+CONVERT(VARCHAR,INCREMENT)+'; {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("GO {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("       ' AS SEQ_SCRIPT {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("  FROM sys.sequences {0}", CommConst.Const_NewLine);

            dtResult = dbHelper.GetDataTable(strSql.ToString(), out strDBName);
            return dtResult;
        }

然后将到查询到的结果导出到文本上,关键代码如下:

// 循环输出存储过程
            foreach (DataRow drSeq in dtSeqTemp.Rows)
            {
                strSeqScriptTemp = CommUtility.ObjToString(drSeq["SEQ_SCRIPT"]);
                strWriteTemp.Clear();
                strWriteTemp.AppendFormat("{0} {1}", strSeqScriptTemp, CommConst.Const_NewLine);

                FileHelper.WriteInfo(strWriteFilePath, CommUtility.ObjToString(strWriteTemp));
            }

sqlserver–函数

/// <summary>
        /// 取得所有函数
        /// </summary>
        public static DataTable GetAllFunction(out string strDBName)
        {
            DataTable dtResult = new DataTable();
            DBHelper dbHelper = new DBHelper();
            StringBuilder strSql = new StringBuilder("");
            strSql.AppendFormat("SELECT  {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("       sysobjects.name   AS NAME {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("       ,syscomments.text AS SCRIPT {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("  FROM sysobjects {0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" INNER JOIN syscomments {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("    ON sysobjects.id=syscomments.id {0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" WHERE 1=1  {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("   AND sysobjects.[type] in ('TF','FN','IF') {0}", CommConst.Const_NewLine);

            dtResult = dbHelper.GetDataTable(strSql.ToString(), out strDBName);
            return dtResult;
        }

然后将到查询到的结果导出到文本上,关键代码如下:

// 循环输出函数
            foreach (DataRow drFun in dtFunctionTemp.Rows)
            {
                strFunctionNameTemp = CommUtility.ObjToString(drFun["NAME"]);
                strFunctionDefinitionTemp = CommUtility.ObjToString(drFun["SCRIPT"]).Replace("'", "''");
                strWriteTemp.Clear();
                strWriteTemp.AppendFormat("/****** Object:  UserDefinedFunction [dbo].[{0}]    Script Date: {1} ******/ {2}", strFunctionNameTemp, dateNow.ToString("yyyy/MM/dd HH:mm:ss"), CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[{0}]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) {1}", strFunctionNameTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("DROP FUNCTION [dbo].[{0}] {1}", strFunctionNameTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("SET ANSI_NULLS ON {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("SET QUOTED_IDENTIFIER ON {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[{0}]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) {1}", strFunctionNameTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("BEGIN {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("EXEC dbo.sp_executesql @statement = N' ");
                strWriteTemp.AppendFormat("{0} {1}'{1}", strFunctionDefinitionTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("END {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);

                FileHelper.WriteInfo(strWriteFilePath, CommUtility.ObjToString(strWriteTemp));
            }

sqlserver–存储过程

/// <summary>
        /// 取得所有存储过程
        /// </summary>
        public static DataTable GetAllProcedure(out string strDBName)
        {
            DataTable dtResult = new DataTable();
            DBHelper dbHelper = new DBHelper();
            StringBuilder strSql = new StringBuilder("");
            strSql.AppendFormat("SELECT SYSO.name,  {0}", CommConst.Const_NewLine); // 存储过程名称
            strSql.AppendFormat("       SYSSM.[definition] {0}", CommConst.Const_NewLine); //存储过程
            strSql.AppendFormat("  FROM sys.all_objects AS SYSO {0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" INNER JOIN sys.sql_modules AS SYSSM {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("    ON SYSO.object_id=SYSSM.object_id {0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" WHERE 1=1 {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("   AND SYSO.is_ms_shipped=0 {0}", CommConst.Const_NewLine);
            strSql.AppendFormat("   AND SYSO.[type] in ('P') {0}", CommConst.Const_NewLine);
            strSql.AppendFormat(" ORDER BY SYSO.[name] ASC {0}", CommConst.Const_NewLine);

            dtResult = dbHelper.GetDataTable(strSql.ToString(), out strDBName);
            return dtResult;
        }

然后将到查询到的结果导出到文本上,关键代码如下:

// 循环输出存储过程
            foreach (DataRow drPro in dtProTemp.Rows)
            {
                strProNameTemp = CommUtility.ObjToString(drPro["name"]);
                strProDefinitionTemp = CommUtility.ObjToString(drPro["definition"]).Replace("'", "''");
                strWriteTemp.Clear();
                strWriteTemp.AppendFormat("/****** Object:  StoredProcedure [dbo].[{0}]    Script Date: {1} ******/ {2}", strProNameTemp, dateNow.ToString("yyyy/MM/dd HH:mm:ss"), CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[{0}]') AND type in (N'P', N'PC')) {1}", strProNameTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("DROP PROCEDURE [dbo].[{0}] {1}", strProNameTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("SET ANSI_NULLS ON {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("SET QUOTED_IDENTIFIER ON {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[{0}]') AND type in (N'P', N'PC')) {1}", strProNameTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("BEGIN {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("EXEC dbo.sp_executesql @statement = N' ");
                strWriteTemp.AppendFormat("{0} {1}'{1}", strProDefinitionTemp, CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("END {0}", CommConst.Const_NewLine);
                strWriteTemp.AppendFormat("GO {0}", CommConst.Const_NewLine);

                FileHelper.WriteInfo(strWriteFilePath, CommUtility.ObjToString(strWriteTemp));
            }

sqlserver、mysql – 表结构

/// <summary>
        /// 取得所有表结构
        /// </summary>
        public static DataTable GetAllDBTableScript(out string strDBName)
        {
            DataTable dtResult = new DataTable();
            DBHelper dbHelper = new DBHelper();
            StringBuilder strSql = new StringBuilder("");

            #region mysql查询表结构

            if (AppConfig.DBType == EnumeDBType.mysql.ToString())
            {
                strSql.AppendFormat(" SELECT  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("         DB_Column.table_name AS '表名' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Table.table_comment AS '表说明' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Column.ORDINAL_POSITION AS '字段序号' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Column.COLUMN_NAME AS '字段名' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Column.COLUMN_COMMENT AS '字段说明' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,'' AS '标识' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,(CASE WHEN DB_Column.COLUMN_KEY ='PRI' THEN '√' ELSE '' END) AS '主键' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Column.DATA_TYPE AS '类型' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Column.CHARACTER_OCTET_LENGTH AS '占用字节数' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,(CASE WHEN DB_Column.CHARACTER_MAXIMUM_LENGTH IS NULL THEN DB_Column.NUMERIC_PRECISION ELSE DB_Column.CHARACTER_MAXIMUM_LENGTH  END )AS '长度' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Column.NUMERIC_SCALE AS '小数位数' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,(CASE WHEN DB_Column.IS_NULLABLE = 'YES' THEN '√' ELSE '' END ) AS '允许空' {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("        ,DB_Column.COLUMN_DEFAULT AS '默认值'        {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("   FROM information_schema.COLUMNS AS DB_Column  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("   LEFT JOIN information_schema.tables AS DB_Table {0}", CommConst.Const_NewLine);
                strSql.AppendFormat(" 	  ON DB_Column.table_name=DB_Table.table_name {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("  WHERE 1=1  {0}", CommConst.Const_NewLine);
                // strSql.AppendFormat("    AND DB_Column.table_schema = 'bianlike'  {0}", CommConst.Const_NewLine);
            }

            #endregion

            #region sqlserver查询表结构

            if (AppConfig.DBType == EnumeDBType.sqlserver.ToString())
            {
                strSql.AppendFormat("SELECT   {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       表名       = Case When A.colorder=1 Then D.name Else '' End,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       表说明     = Case When A.colorder=1 Then isnull(F.value,'') Else '' End,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       字段序号   = A.colorder,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       字段名     = A.name,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       字段说明   = isnull(G.[value],''),  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       标识       = Case When COLUMNPROPERTY( A.id,A.name,'IsIdentity')=1 Then '√'Else '' End,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       主键       = Case When exists(SELECT 1 FROM sysobjects Where xtype='PK' and parent_obj=A.id and name in (  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("                        SELECT name FROM sysindexes WHERE indid in( SELECT indid FROM sysindexkeys WHERE id = A.id AND colid=A.colid))) then '√' else '' end,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       类型       = B.name,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       占用字节数 = A.Length,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       长度       = COLUMNPROPERTY(A.id,A.name,'PRECISION'),  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       小数位数   = isnull(COLUMNPROPERTY(A.id,A.name,'Scale'),0),  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       允许空     = Case When A.isnullable=1 Then '√'Else '' End,  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("       默认值     = isnull(E.Text,'')  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("  FROM syscolumns A  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("  Left Join systypes B  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("    On A.xusertype=B.xusertype  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat(" Inner Join sysobjects D  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("    On A.id=D.id  and D.xtype='U' and  D.name<>'dtproperties'  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("  Left Join syscomments E  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("    on A.cdefault=E.id  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("  Left Join sys.extended_properties  G  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("    on A.id=G.major_id and A.colid=G.minor_id  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("  Left Join sys.extended_properties F  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("    On D.id=F.major_id and F.minor_id=0  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat("      --where d.name='OrderInfo'    --如果只查询指定表,加上此条件  {0}", CommConst.Const_NewLine);
                strSql.AppendFormat(" Order By A.id,A.colorder  {0}", CommConst.Const_NewLine);
            }

            #endregion            

            dtResult = dbHelper.GetDataTable(strSql.ToString(), out strDBName,true);

            return dtResult;
        }

然后将到查询到的结果导出到Excel上(使用的ClosedXML导出Excel),关键代码如下:

// 把模板文件复制到要导出的Excel文件中
                File.Copy(strExcelTempFilePath, strExportExcelFilePath, true);
                using (ExcelUtility excel = new ExcelUtility(strExportExcelFilePath))
                {
                    // 打开要导出的Excel文件
                    excel.OpenExcelFile();
                    // 表名称
                    //string strDBTableNameTemp = $"{intTableIndex}_{CommUtility.ObjToString(dtTemp.Rows[0]["表名"])}";
                    string strDBTableNameTemp = CommUtility.ObjToString(dtTemp.Rows[0]["表名"]);
                    string strDBTableDescTemp = CommUtility.ObjToString(dtTemp.Rows[0]["表说明"]);
                    // 完整名称(索引_表名)
                    string strFullDBTableNameString = $"{intTableIndex}_{CommUtility.ObjToString(dtTemp.Rows[0]["表名"])}";
                    // 截取后的表名称(最大长度31位)
                    string strCutDBTableNameString = strFullDBTableNameString;
                    if (strCutDBTableNameString.Length >= 30)
                    {
                        strCutDBTableNameString = strCutDBTableNameString.Substring(0, 31);
                    }

                    // 循环查询的表信息
                    foreach (DataRow drTemp in dtTemp.Rows)
                    {
                        // 如果当前行表名字段不为空,并且不等于上一个表名
                        if (intTalbeListRowIndex == 3
                            || (CommUtility.ObjToString(drTemp["表名"]) != ""
                                && CommUtility.ObjToString(drTemp["表名"]) != strDBTableNameTemp))
                        {
                            strDBTableNameTemp = CommUtility.ObjToString(drTemp["表名"]);
                            strDBTableDescTemp = CommUtility.ObjToString(drTemp["表说明"]);
                            // 完整名称(索引_表名)
                            strFullDBTableNameString = $"{intTableIndex}_{CommUtility.ObjToString(drTemp["表名"])}";
                            // 截取后的表名称(最大长度31位)
                            strCutDBTableNameString = strFullDBTableNameString;
                            if (strCutDBTableNameString.Length >= 31)
                            {
                                strCutDBTableNameString = strCutDBTableNameString.Substring(0, 31);
                            }

                            // 切换Excel的sheet到表一览sheet
                            excel.SelectActiveSheet("表一览");
                            //追加一行
                            excel.RowInsert(intTalbeListRowIndex + 1, 1);

                            // 写上当前表名、表描述
                            excel.SetValue("B" + intTalbeListRowIndex, "'" + strFullDBTableNameString); // 表名
                            excel.SetValue("C" + intTalbeListRowIndex, "'" + strDBTableDescTemp); // 表说明
                            // 判断导出的Excel中指定sheet是否存在,不存在创建
                            intSheetExistTemp = excel.IsSheetExsists(strDBTableNameTemp);
                            if (intSheetExistTemp < 0)
                            {
                                // 添加sheet,将表模板sheet复制到新创建的sheet中
                                excel.AddNewSheet(strCutDBTableNameString, strCopyTableSheetName);
                                // 添加链接
                                excel.AddHyperLink("B" + intTalbeListRowIndex, strCutDBTableNameString, "C3");
                                // 切换到新创建的Sheet上
                                excel.SelectActiveSheet(strCutDBTableNameString);
                                intTalbeScriptRowIndex = 7;
                            }
                            // sheet表一览行号加1
                            intTalbeListRowIndex++;
                            intTableIndex++;
                        }

                        excel.SetValue("C3", "'" + strFullDBTableNameString); // 表名
                        excel.SetValue("C4", "'" + strDBTableDescTemp); // 表说明

                        //追加一行
                        excel.RowInsert(intTalbeScriptRowIndex + 1, 1);

                        excel.SetValue("B" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["字段序号"])); // 字段序号
                        excel.SetValue("C" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["字段名"])); // 字段名
                        excel.SetValue("D" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["字段说明"])); // 字段说明
                        excel.SetValue("E" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["标识"])); // 标识
                        excel.SetValue("F" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["主键"])); // 主键
                        excel.SetValue("G" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["类型"])); // 类型
                        excel.SetValue("H" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["占用字节数"])); // 占用字节数
                        excel.SetValue("I" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["长度"])); // 长度
                        excel.SetValue("J" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["小数位数"])); // 小数位数
                        excel.SetValue("K" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["允许空"])); // 允许空
                        excel.SetValue("L" + intTalbeScriptRowIndex, "'" + CommUtility.ObjToString(drTemp["默认值"])); // 默认值
                        intTalbeScriptRowIndex++;
                    }
                    excel.DeleteSheet(strCopyTableSheetName);
                    excel.DeleteSheet(strCopyTableDataSheetName);
                    excel.SaveFile();
                }

表结构的效果图如下图:

mysql 导出表物理结构 mysql导出表结构sql_mysql


mysql 导出表物理结构 mysql导出表结构sql_mysql_02