ASP中使用数据形成展示多层数据

来源:互联网 发布:net.sft.json maven 编辑:程序博客网 时间:2024/05/07 09:13

关系数据库数据集合靠的是表与表之间的关系联结起来的。很多情况下数据表是以父子关系联结,例如下面的这两张表:

[Bibliotheca]
ID Name
1   a
2   b
3   c
4   d

[Book]
ID CID Name Dept
1   1   a    x
2   1   a    y
3   1   a    z
4   2   b    x
5   2   b    z
6   3   c    z
7   4   d    x
8   4   d    z
9   4   d    z

表一[Bibliotheca]为父表,表示书目信息,表二[Book]为子表,对应着具体的图书。书库中有一份书目,可以供借阅人查阅,每一份书目下都有1-N本具体的图书,而每本书实际上属于不同的部门所有,例如上表中名为《a》的书共有3本,分别属于x,y,z三个部门。
倘若需要做一个查询,显示每一书(应该是说名为*的书)分别属于哪些部门,数量是多少,要返回这样一个记录集就比较麻烦,该查询结果如同下表。
[result]
Name  Dept List  count
a     x,y,z      3
b     x,z        2
c     z          1
d     x,z        3
一般情况下,web页面要显示下面的结构的查询结果,需要使用一条select * from [Book] Order By CID返回整个Book表,然后循环整个Recordset表,遇到CID相同的Book,则数量递增,显示Dept Name,当遇到不同的CID的时候,显示Count,然后Count清零,显示新的Name。代码如下:
Count = 1
this_CID = 0
last_CID = 0
Do While Not rst.Eof
 this_CID = rst("CID")
 If this_CID <> last_CID Then Response.Write rst("Name") & "&nbsp;"
 Response.Write rst("Dept") & ","
 last_CID = this_CID
 rst.moveNext
 If rst.Eof Then
  Response.Write "&nbsp;" & Count
  Exit Do
 Else
  If last_CID <> rst("CID") Then
   Response.Write "&nbsp;" & Count & "<br>"
  Else
   Count = Count + 1
  End If
 End If
Loop
这样的查询结果集的缺点是显而易见的,父表每一行对应子表的数据行少的话,还没有关系,一旦对应关系很多,就会产生大量的冗余数据。
要避免数据冗余这样的问题,还可以使用存储过程来建立临时表,通过几个查询来生成临时表数据,在Web页面中使用Recordset访问临时表即可。而临时表也有不少问题,首先会话断开的时候得清除临时表,其次只能用一个字段来表示关联的数据集合,在程序当中还得写分解程序。

上述问题就是我上周写的一个图书管理系统所遇到的,当然具体的表和查询的结果,略有出入,只是为了比较清晰明了的说明问题,结构大致相当即可。
我使用了微软的数据访问组件中的MSDataShape数据形成数据服务程序来解决显示父子表层次关系的问题,它完全避免了上述两种方法的弊端。
使用MSDataShape服务程序,产生的Recordset,不在是一个单表的结果集,而是一个具有分层结构的结果集和。

访问MSDataShape服务

为了访问MSDataShape服务程序,需要修改一下你的数据库联接字符串,由于MSDataShape是OLE DB服务程序的一部分,因此原先的数据库联接必须是OLE DB提供的连接,而无法使用ODBC提供的连接。
原先的OLE DB数据库联接字符串如果为:
ConnString = "Provider=SQLOLEDB;Data Source=myDBServer;Initial Catalog=TestDB"
那么只需要在ConnString前面加上串字符"Provider=MSDataShape;Data "就可以了
DSConnString = "Provider=MSDataShape;Data " & ConnString
使用ADO Connection对象打开数据连接
Conn.Open DSConnString
就可以用Recordset读取层次记录集了。

查询生成记录集
打开连接之后,你还得为Recordset提供访问的查询命令字符串,为了生成上面所说的结果集,你的SQL命令应该这么写:
strSQL = "shape{select * from [Bibliotheca]} as Bibliotheca" _
 & " append({select ID,CID,dept from [Book]} as Book relate ID To CID) as Book" _
 & " ,Count(Book.ID) as BookCount"

接下来就可以读取Recordset了,然后Response查询结果表
rst.Open strSQL,Conn
Set rstBook = rst("Book")
Do While Not rst.Eof
 Response.Write rst("Name") & "&nbsp;"
 Do While Not rstBook.Eof
  Response.Write rstBook("dept") & ","
  rstBook.MoveNext
 Loop
 Response.Write "&nbsp;" & rst("BookCount") & "<br>"
Loop

需要说明的是查询语句的写法,MSDataShape的SQL查询有三个关键词:shape、append、relate。
shape{select * from [Bibliotheca]} as bibliotheca
append({select ID,CID,dept from [Book]} as Book relate ID To CID) as Book,
Count(Book.ID) as BookCount

shape之后{}中的查询语句是父表的查询,然后使用as将其命名为bibliotheca。append表是往Recordset添加字段,字段的数据在之后的()中,()内的{}中是子表的查询,用as将其命名为Book,relate之后表示父表的ID和子表的CID存在对应关系,as表示子查询为父表的字段Book,还可以用聚合函数来计算Book Count。

 

2003/12