Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1792510
  • 博文数量: 600
  • 博客积分: 10581
  • 博客等级: 上将
  • 技术积分: 6205
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-06 10:13
文章分类
文章存档

2016年(2)

2015年(9)

2014年(8)

2013年(5)

2012年(8)

2011年(36)

2010年(34)

2009年(451)

2008年(47)

分类:

2009-10-11 11:17:16

来源:cww

我原本是XBase的程序设计者,初用Access的数据库时,有很多的观念一时转不过来,
如果您也是一位XBase的旧有使用者,倒可叁考一下。相信有了这一些的补充说明,不管
XBase或Access的使用者,对於.MDB 的控制会更加的顺手。

1.有索引的Seek指令:
  和Xbase相同,要先设定依哪一个Index来Search,这是Search中最快的一种,但是最
  大的限制在於它只能用於dbOpenTable的方式
  Set RS = DB.OpenRecordSet("MyTable", dbOpenTable)
  RS.Index = "TheIndex" '设定Index的名称

  RS.Seek compare, key1 ,key2 , key3 ...,key13

  compare: =  >=  >   <=  <
  key1 ... key13:key值,如果是复合键key2 ..key13才有资料

  如果我们Search只是key值中的部份值,那该如何:
    XBase 假设该key长度一共8个byte,我们只想找前三码相同者  
       Set Exact off
       Set Index to TheKey
       srhKey = "123"
       Seek srhKey    
       If Found() then ....
    VB 的做法
       RS.Index = "TheKey" 
       srhKey = "123"
       Seek ">=" , srhKey
       If Not RS.NotMatch then....

  如果是复合键,而我们只找前面符合者,後面的不管
 
    XBase 假设该key由Field Fld1与Field Fld2所组成Index on Fld1+Fld2 to TheKeys 
          我们只想找Fld1相同者,Fld2不管  
       Set Exact off
       Set Index to TheKeys
       srhKey = "123"
       Seek srhKey    
       If Found() then ....
    VB 的做法
       RS.Index = "TheKeys" 
       srhKey = "123"
       Seek ">=" , srhKey
       If Not RS.NotMatch then....
  VB不可以用 Seek  "=" , srhKey 
    因为这样做的意义是 Seek "=", srhKey,  Null  即第二个Field要是Null者才能
    够符合条件。    
  以上的Seek都是Search第一笔符合条件者,之後再使用
  Xbase的Skip  VB RecordSet的 Move系列指令(Move MoveFirst MoveNext MovePrevious
  MoveLast)来找下一笔符合条件者,要特别提出的是VB的特性:
  如果Seek指令配合 =, > , >= 者,那Seek後指到的是第一笔符合条件者,查下一笔笔
  有没有符合条件,则是使用RecordSet的 MoveNext 指令来移动,而後再Check,然而
  如果Seek 指令配合着 < , <= 来用时,则会指到最後一笔符合条件者,所以要使用
  MovePrevious来Check上一笔是否符合(当然,我也可用MoveNext来Check,但一定不符
  合就是了)。  

  如果Seek 指令没有找到符合条件者,这时XBase与VB又有很大的不同,
XBase VB
EOF() True RS.Eof False
Found() False RS.NotMatch True
目前Record RecordCount() + 1 Current Record 没有Current Record
2.Dynaset的Search
  RecordSet使用dbOpenDynaset dbOpenSnapshot不能使用Seek,而要使用Find系列的
  指令 FindFirst/FindNext/FindPrevious/FindLast,
  而相对的dbOpenTable的方式则不能用Find系列的指令,这个限制我觉得大了一些,
  其实让dbOpenTable的RecordSet也来做一下Find又何妨,速度慢而以,就好比Xbase
  不管有没有Index都可以用Locate,只是速度慢。
  例:
     srhstr = "Age > 17"
     RS.FindFirst srhstr

  这srhstr的内容就好比是SQL Where中的Statement,这和XBase的Find指令不相同,
  与XBase的Locate也不尽相同但比较像。Find指令特性
Find method     Begins searching at     Search 方向
FindFirst       Beginning of recordset  向後找 
FindLast        End of recordset        向前找 
FindNext        Current record          向後找 
FindPrevious    Current record          往前找 
而且Find指令是一笔一笔的找,而不管Table有没有Index,所以了,使用Find系列指令
之前应使用SQL 的Where指令将RecordSet 所含的笔数减少,否则很慢。 

注:没有FindFirst/FindLast 之前不要用 FindNext FindPrevious,否则取到的Current
    Record会不知是何者就是了。

移动Current Record的另外一种方式使是Move 系列指令,这不管是dbOpenTable
dbOpenDynaset dbOpenSnapshot都可以用,
XBase VB
Go Top MoveFirst
Go Bott MoveLast
Skip MoveNext
Skip -1 MovePrevious
Skip N Move N
  			
3.Record NO与BookMark 的问题
  在Xbase中,最常用的技巧便是记录Record No,而後不管Current Record移到何方,
  只要使用Go 指令便可以将Current Record指回来,在VB呢,不太相同,VB没有
  绝对 Record No的观念,而要用BookMark的方式,而这不管是使用dbOpenTable,
  dbOpenDynaset, dbOpenSnapshot都可以,但不能用於dbOpenForwardOnly
  
  Dim BK as Variant 
  
  Set RS = OpenRecordSet("MyTable")
   .
   .
  BK = RS.BookMark  '设定BookMark
   .
   .
  RS.BookMark = BK '设定Current Record成上面BK=RS.BookMark时的那一笔   
  
  但是BookMark可不是完全替代XBase的Go 指令之技巧,如果RecordSet在中途ReQuery
  了,那麽原先记录的BookMark也随之无效了。而且,BookMark和Record No也有很大
  的不同,如果我们有两个RecordSet:

  Set RS1 = DB.OpenRecordSet("Select * from myTable")
  Set RS2 = DB.OpenRecordSet("Select * from myTable")

  那麽RS1所设的BookBark不能被RS2所使用(即 BK = RS1.BookMark : 
  RS2.BookMark = BK 不可行)。
  最後,并不是所有的RecordSet都有提供BookMark的功能,要Check一下BookMarkable
  是否为True。

4.比XBase好的地方 - Clone
  在第3点中我们提到两个RecordSet可以指向相同的Table范围,这在Xbase中可不行,
  XBase中一个Table只能在程序中引用一次,如果有必要两个引用,而且各自有各自的
  Current Record时,XBase设计起来比较累,要不断的记录Current Record的RecNo,
  而後Move到其他Record,之後再使用Go指令Move回来,但VB则不是,可以有两个不同
  的RecordSet引用,而且各自有其Current Record。不只如此,如果只是想各自有其
  Current Record,那可以使用RecordSet的Clone方法,它会Duplicate另一个RecordSet

  Set RS1 = DB.OpenRecordSet("Select * from myTable")
  Set RS2 = RS1.Clone
  
  这样RS2与RS1有个自的Current Record,而且二者的记录BookMark的变数可共用,
  (即 BK = RS1.BookMark : RS2.BookMark = BK 可行),用Clone的方式其效率也比
  像第3点中开两个RecordSet来得好。	

5.新增、删除
XBase                                    VB

Append Blank 後,便新增一笔空白列        RecordSet的AddNew,一直到.Update 後才新增

Append Blank後不能不要新增了             RecordSet.CancelUpdate取消新增

新增完後,CurRecNo指向新增的那一笔       新增後,指向新增前的那一笔,如果想指向新增
                                         的那一笔,使用RS.BookMark=RS.LastModified
					 如果是dbOpenDynaset,新增的那一笔会出现在
                                         最後一笔,而且就算新增的那一笔的资料内容,
                                         不在RecordSet SQL Where的范围内,该笔仍是在
                                         RecordSet的最後一笔,要用.Requery才能重排。
                                         若是dbOpenTable,那新增者未必是落在最後一笔
                                         若有Index,则会落在正确处,否则也未必是最後
                                         一笔,因为同时可能也有人在新增。

删除後停在原来删除当笔,用GO指令         删除後,就没有Current Record,而且BookMark
仍可指到该笔                             不能再指回该笔。


6.TransAction 的问题
  传统的XBase没有TransAction的做法,而如果配合Novell,倒是可以利用Novell的功
  能而做出Transaction,不过後来的XBase,也附有Transaction的功能了,只是本人
  VFP, Delphi的数据库功能忘得差不多了,实做不出比较。

  VB的Transaction不是放在DataBase的物件之中,而是放在WorkSpace物件与DBEngine之
  中,到现在我还是不明白为什麽要这个样子。(Delphi的Transaction是TDatabase的方法)

  BeginTrans
  CommitTrans
  RollBack

  用法不多加说明,但特别要提出的是,这三者是WorkSpace的方法,而一个WorkSpace
  中可以有多个DataBases,而这三个方法影响的层面是WorkSpace内所有的DataBases,
  而不是单一的一个Database,当然了,并不是所有的DataBase都可以受Transaction的
  控制,例如Dbase3+的Database被Jet Engine所Open,在VB中它也是一个Database,
  但是Database物件的Transactions属性将是False,表示不受TransAction的作用。
  同一个 WorkSpace的Transaction最多可以有5 层,但过ODBC者只有一层。
  如:
    Workspaces(0).BeginTrans '外层Transaction
    .... 
    Workspaces(0).BeginTrans '内层Transaction
    rs.AddNew
    rs.Fields("id") = CLng(Text1.Text)
    rs.Fields("name") = Text2.Text
    rs.Update
    Workspaces(0).CommitTrans '内层Commit
    ....
    Workspaces(0).Rollback    '但for some reasons, 外层RollBack
    那麽这新增将没有成功 

注:如果使用Transaction则不管RecirdSet.LockEdit是True/False,都会变成悲观
    锁定(True)

阅读(1084) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~