因經常需要處理大數量的表,因此查看表結構、數據量、以及索引情況基本上成為了常態,無奈生產環境的數據庫不讓我們直接訪問,因此想要了解到生產環境的數據庫的表結構和索引信息變得很麻煩需要經常找DBA幫忙找,而想查看具體某個表的數據量使用 select count(1) from table方法的效率實在慢的無法忍受,正所謂求人不如求己,花了點時間自己做了個查看數據庫表結構和索引的小工具順便溫習了下系統表一舉兩得,喜歡的朋友可以拿去用用。
工具功能很簡單但勝在實用(尤其是不讓開發人員用企業管理連接生產環境數據庫時,簡直是一大殺器),可以提高不少效率
1.根據鏈接字符串列出服務器上所有的數據庫以及表。
2.查看表的記錄數、字段及索引(包含覆蓋索引)信息。
默認界面如下
根據需要修改好數據連接串,點擊 鏈接 自動查詢出數據庫信息
雙擊數據庫加載所有的表並讀取表的記錄數(表名后面括號里的數字代表記錄數)
雙擊表名稱加載表的結構和索引信息
這里對列表字段做個簡單翻譯,以幫助英語不好的童鞋
ColumnName | ColumnType | ByteLength | CharLength | Scale | IsIdentity | IsNullable | Remark |
字段名稱 | 字段類型 | 字節長度 | 字符長度 | 小數位數 | 是否自增列 | 是否允許空 | 字段說明 |
IndexName | IndexType | IsPrimaryKey | IsUnique | IsUniqueConstraint | IndexColumns | IndexIncludeColumns |
索引名稱 | 索引類型 | 是否主鍵 | 是否唯一 | 是否唯一約束 | 索引包含的列 | 覆蓋索引包含的列 |
表結構里的Remark字段說明就是我們給列加的那個列說明,ByteLength是字段的字節長度,CharLength是字符長度,這兩個主要是針對nchar,nvarchar類型的在數據庫中比如定義 Name nvarchar(50),顯示的字節長度是100,字符長度才是50(nvarchar一個字符占兩個字節),不注意的話會很慘,曾經被這個玩意給害死(喜歡使用alt+F1 查看表結構信息,這時nvarchar(50)的字段類型會顯示長度為 100)
表索引里面IndexColumns表示索引所包含的列,IndexIncludeColumns表示覆蓋索引所包含的列,比如:索引IX_Test1,IndexColumns為Name,Email,IndexIncludeColumns為Address,PostCode,覆蓋索引只能建立在非聚簇索引上,主要是為了解決書簽查找(RID、鍵查找),聚簇索引不存在書簽查找所以不能創建覆蓋索引,在此不再詳述
create index IX_Test1 on Users(Name,Email) include(Address,PostCode)
恩,功能就這么簡單,利用好了能在工作中省下不少事情,貼一下主要代碼

public static class SqlQuery { public static List<string> GetDatabases(string connString) { string sql = "select name from sys.databases where name not in ('master','model','msdb','tempdb')"; DataTable dt = DbHelperSQL.GetDataTable(connString, sql); return dt.Rows.Cast<DataRow>().Select(row => row["name"].ToString()).ToList(); } public static Dictionary<string, string> GetTables(string connString, string database) { string sql = string.Format(@"select objects.name+'('+ltrim(str(rows))+')' showname, objects.name from {0}.sys.objects inner join {0}.dbo.sysindexes on objects.object_id=sysindexes.id and sysindexes.indid<=1 where type='U' order by objects.name", database); DataTable dt = DbHelperSQL.GetDataTable(connString.Replace("master", database), sql); return dt.Rows.Cast<DataRow>().ToDictionary(row => row["showname"].ToString(), row => row["name"].ToString()); } public static DataTable GetColumns(string connString, string database, string tableName) { string sql = string.Format(@"select columns.name ColumnName, types.name ColumnType, columns.is_identity IsIdentity, columns.is_nullable IsNullable, cast(columns.max_length as int) ByteLength, ( case when types.name='nvarchar' and columns.max_length>0 then columns.max_length/2 when types.name='nchar' and columns.max_length>0 then columns.max_length/2 when types.name='ntext' and columns.max_length>0 then columns.max_length/2 else columns.max_length end ) CharLength, cast(columns.scale as int) Scale, extended_properties.value Remark from {0}.sys.columns inner join {0}.sys.types on columns.system_type_id=types.system_type_id and columns.user_type_id=types.user_type_id left join {0}.sys.extended_properties on columns.object_id=extended_properties.major_id and columns.column_id=extended_properties.minor_id where object_id=OBJECT_ID(@tableName) order by columns.column_id", database); SqlParameter param = new SqlParameter("@tableName", SqlDbType.NVarChar, 100) { Value = database + ".dbo." + tableName }; DataTable dt = DbHelperSQL.GetDataTable(connString, sql, param); return dt; } public static DataTable GetIndexs(string connString, string database, string tableName) { #region SQL string sql = string.Format(@"with IndexCTE as ( select indexes.object_id, indexes.index_id, indexes.name IndexName, indexes.type_desc IndexType, indexes.is_primary_key IsPrimaryKey, indexes.is_unique IsUnique, indexes.is_unique_constraint IsUniqueConstraint from {0}.sys.indexes where object_id =OBJECT_ID(@tableName) ) ,IndexColumnTempCTE as ( select ic.object_id, ic.index_id, ic.column_id, ic.index_column_id, ic.is_included_column, cast(c.name as nvarchar(max)) columnname, CAST(null as nvarchar(max)) includekey from {0}.sys.index_columns ic inner join {0}.sys.columns c on ic.column_id=c.column_id and ic.object_id=c.object_id where ic.index_column_id=1 and ic.object_id =OBJECT_ID(@tableName) union all select ic.object_id, ic.index_id, ic.column_id, ic.index_column_id, ic.is_included_column, case ic.is_included_column when 0 then columnname+','+c.name end, case when ic.is_included_column = 1 and includekey is null then c.name when ic.is_included_column = 1 and includekey is not null then includekey+','+c.name end from {0}.sys.index_columns ic inner join IndexColumnTempCTE cte on cte.index_id=ic.index_id and cte.index_column_id+1=ic.index_column_id and cte.object_id=ic.object_id inner join {0}.sys.columns c on ic.column_id=c.column_id and ic.object_id=c.object_id ), IndexColumnCTE as ( select object_id, index_id, max(columnname) IndexColumns, max(includekey) IndexIncludeColumns from IndexColumnTempCTE group by object_id,index_id ) select IndexCTE.IndexName, IndexCTE.IndexType, IndexCTE.IsPrimaryKey, IndexCTE.IsUnique, IndexCTE.IsUniqueConstraint, IndexColumnCTE.IndexColumns, IndexColumnCTE.IndexIncludeColumns from IndexCTE inner join IndexColumnCTE on IndexCTE.object_id=IndexColumnCTE.object_id and IndexCTE.index_id=IndexColumnCTE.index_id order by IndexCTE.object_id", database); #endregion SqlParameter param = new SqlParameter("@tableName", SqlDbType.NVarChar, 100) { Value = database + ".dbo." + tableName }; return DbHelperSQL.GetDataTable(connString, sql, param); } }

public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void btnConn_Click(object sender, EventArgs e) { try { string connString = this.txtConnString.Text; List<string> list = SqlQuery.GetDatabases(connString); this.treeView1.Nodes.Clear(); this.treeView1.Nodes.AddRange(list.Select(item => new TreeNode { Text = item }).ToArray()); } catch (Exception ex) { MessageBox.Show(ex.GetBaseException().Message, "系統異常", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void treeView1_DoubleClick(object sender, EventArgs e) { try { string connString = this.txtConnString.Text; TreeNode node = this.treeView1.SelectedNode; switch (node.Level) { case 0: node.Nodes.Clear(); node.Nodes.AddRange(SqlQuery.GetTables(connString, node.Text).Select(kv => new TreeNode { Text = kv.Key, Tag = kv.Value }).ToArray()); node.Expand(); break; case 1: this.gridColumns.DataSource = SqlQuery.GetColumns(connString, node.Parent.Text, node.Tag.ToString()); this.gridIndexs.DataSource = SqlQuery.GetIndexs(connString, node.Parent.Text, node.Tag.ToString()); break; } } catch (Exception ex) { MessageBox.Show(ex.GetBaseException().Message, "系統異常", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
附上源碼下載:SqlQueryAnalyzer.rar
release目錄下為已經編譯好的程序SqlQueryAnalyzer.exe可以直接打開使用,src目錄為源碼