xyzjr 发表于 2015-6-27 09:02:58

Sql Server表结构及索引查询器

  因经常需要处理大数量的表,因此查看表结构、数据量、以及索引情况基本上成为了常态,无奈生产环境的数据库不让我们直接访问,因此想要了解到生产环境的数据库的表结构和索引信息变得很麻烦需要经常找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)

  恩,功能就这么简单,利用好了能在工作中省下不少事情,贴一下主要代码


SqlQuery.cs


public static class SqlQuery
{
public static List 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().Select(row => row["name"].ToString()).ToList();
}
public static Dictionary 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.indid0 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);
}
}

Form1.cs


public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnConn_Click(object sender, EventArgs e)
{
try
{
string connString = this.txtConnString.Text;
List 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目录为源码
页: [1]
查看完整版本: Sql Server表结构及索引查询器