数据约束控件和 RecordSet
数据约束控件是指要求与Data 控件连接到一起的控件, 如DBGird 等。典型的特征是都有一个DataSource 属性, 该属性在运行时是不可用的。 在没有使用数据控件Data 而采用DAO 命令打开一个数据库后,如何将表中记录显示在数据约束控件内?方法如下:
约束控件在设计时应该连接到一个空的 DATA1,
在运行中:
Set DATA1.Recordset = 没有使用数据控件建立的Recordset
刷新该数据约束控件, 注意不能刷新DATA1。
由 awing 提供的例子如下:
在一个窗体内建立一个文本控件和一个数据控件,将文本控件的DataSource属性指向Data1,设置对应的字段,然后编下如程序:
dim db as database
dim rs as recordset
set db=opendatabase("temp.mdb")
set rs =db.openrecordset("files",dbopentable)
set data1.recordset=rs
运行程序后,点击数据控件的移动记录。
返回
语言选择引起的查询错误
平常在我们新建数据库时, 一般都使用了以下的代码:
Set database = workspace.CreateDatabase (name, locale, options)
而在 locale 中, 如果您使用了 dbLangGeneral, 一些古怪的情况就会出现, 例如在 "select * from db where name like '陈*'", 结果您会发现所有姓 "池" 的人, 也出现的结果中, 在用 rs.findfirst "city like '温州*'", 结果是不会定位在温州, 而是找到的广州或北京。。
这一切都是因为使用了 dbLangGeneral导致的,简体中文的正确选择是 dbLangChineseTraditional 。 应该注意的是, 在其他数据库如 SQL Server 也有类似的情况。
BTW: 在locale 中设置数据库的口令, 方法是:
dbLangChineseTraditional & ";pwd=NewPassword"
返回
非法退出引起的 RecordCount记数错误
感谢 zhuyongming 提供。
Access 表里无记录,但 RecordCount 却显示记录为1。后来发现该表曾经非法退出造成的, 又复制了一个表就好使了。
返回
不用 EOF 以加快记录循环
通常我们使用以下的代码进行记录循环:
Do while not records.eof
combo1.additem records![Full Name]
records.movenext
loop
结果是每个循环中数据库都要进行一次数据结束测试。在大量的记录的情况下, 浪费的时间相当大。 而使用以下的代码, 可以提高近 1/3 的速度:
records.movelast
intRecCount=records.RecordCount
records.movefirst
for intCounter=1 to intRecCount
combo1.additem records![Full Name]
records.movenext
next intCounter
返回
断开所有的数据连接
如果在代码中使用了数据控件如 DAO, RDO, 或 ADO, 在退出时应该关闭所有打开的 recordset, database,和 workspace 。 虽然对象能自动注销, 但是数据连接不会马上断开, 可能会导致一些内存不能被系统重新分配。
下面的代码可以关闭所有打开的 DAO workspace, 并释放所占的内存。
Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
'
Dim ws As Workspace
Dim db As Database
Dim rs As Recordset
'
For Each ws In Workspaces
For Each db In ws.Databases
For Each rs In db.Recordsets
rs.Close
Set rs = Nothing
Next
db.Close
Set db = Nothing
Next
ws.Close
Set ws = Nothing
Next
'
End Sub
返回
取得下个自动生成的 ID
在许多数据库里我们使用了自动增加的 ID, 能取得下个自动产生的 ID, 意味着在数据增加后, 不再需要使用 LastModified 属性和 bookmarks。
With Data1.Recordset
.AddNew
MsgBox !ID '下个自动生成的 ID
.CancelUpdate
End With
返回
用DATA控件绑定报表控件打印报表
1 在数据库中生成一TEMP表。
2 用报表生成器生成报表,然后删除数据库中的TEMP表。
3 在VB中打开数据库,用OPENRECORDSET语句生成一个RECORDSET
(此RECORDSET的结构要与第一步生成的TEMP表一样,但记录数可以
用WHERE子句限制)
用SET DATA1.RECORDSET=RS(RECORDSET)将RECORDSET的数据赋予数据控件。
4 设定报表控件的REPORTFILENAME属性为报表文件名;
REPORTSOURCE属性为3;
DATASOURCE属性为数据控件名
5 执行ME.CR1.ACTION=1即可打印。
但我不知如何直接利用RECORDSET中的数据,如果你知道请告知。
感谢由 FENG 提供该技巧。
返回
取得正确的 RecordCount 值
特别是在 RecordSet 中记录比较多的情况,在更新 RecordSet 后 RecordCount 返回的值一般比真实的值要小, 以下的方法可以保证得到正确的值:
Data1.Recordset.MoveLast
RCount = Data1.Recordset.RecordCount
返回
锁住数据库中的表
把表达式 True=False 放到表的 ValidationRule 属性就能锁上。 HardLockTable 实现了该功能。
声明
Public MyDB As Database
Dim Dummy As Integer
函数
Function HardLockTable (ByVal whichAction As String, ByVal aTable As String) As Integer
On Error GoTo HardLockTableError
HardLockTable = True
Select Case whichAction
Case "Lock"
MyDB.TableDefs(aTable).ValidationRule = "True=False"
MyDB.TableDefs(aTable).ValidationText = "This table locked via " & "ValidationRule on " & Now
Case "UnLock"
MyDB.TableDefs(aTable).ValidationRule = ""
MyDB.TableDefs(aTable).ValidationText = ""
Case "TestThenUnLock"
If MyDB.TableDefs(aTable).ValidationRule = "True=False" Then
MyDB.TableDefs(aTable).ValidationRule = ""
MyDB.TableDefs(aTable).ValidationText = ""
End If
End Select
HardLockTableErrorExit:
'subFlushDBEngine
'optional, see next suggestion
Exit Function
HardLockTableError:
HardLockTable = False
MsgBox Error$ & " error " & "in HardLockTable trying " & "to " & whichAction & " " & aTable
Resume HardLockTableErrorExit
End Function
使用例子
'上锁
Dummy = HardLockTable("Lock", "TestTable")
' 开锁
Dummy = HardLockTable("UnLock", "TestTable")
返回
Data 控件使用有密码的 Access 数据库
使用 Data 控件打开 Accecc 数据库:
设置 Connect 属性为 ;pwd=密码
Data1.Connect = ";pwd=密码"
修改密码:
Data1.Database.NewPassword _老密码_, _新密码_
返回
处理在 Access 数据库中的 Null 值
Access 的字符串字段可以包含 NULL 值。在读这些字段到 VB 的 String 变量时,会出现运行时间的错误。最好的解决方法是使用 & 操作符将该字段与空串连接:
sString = "" & RS(0)
返回
表或查询是否存在
在 VB5 中需要 Microsoft DAO 3.x Object Library。
Public Const NameNotInCollection = 3265
Dim DB As Database
Private Function ExistsTableQuery(TName As String) As Boolean
Dim Test As String
On Error Resume Next
' 该名字在表名中是否存在。
Test = db.TableDefs(TName).Name
If Err <> NameNotInCollection Then
ExistsTableQuery = True
' Reset the error variable:
Err = 0
' 该名字在查询中是否存在。
Test = db.QueryDefs(TName$).Name
If Err <> NameNotInCollection Then
ExistsTableQuery = True
End If
End If
End Function
返回
连接Data到多个表单
假设 Form1,Form2 表单都有 Data 控件,在 Form2 的 Form_Load 事件中加入以下的代码,可以实现对DATA 的多个连接。
Sub Form_Load ()
Set Data1.Recordset = Form1.Data1.Recordset
End Sub
返回
处理 Select 语句中的单引号
在数据库应用中, 经常要动态生成 Select 语句,典型的情况:
SqlString = "Select * from myBas where Name = '" & Text1 & "'"
好啦, 问题出现了, 如果在录入的 Text1 中有一个单引号,结果是把 SqlString 发给数据库时, 将出错!
其实要做的防范很简单, 增加一个函数:
FUNCTION CheckString (s) as String
pos = InStr(s, "'")
While pos > 0
s = Mid(s, 1, pos) & "'" & Mid(s, pos + 1)
pos = InStr(pos + 2, s, "'")
Wend
CheckString="'" & s & "'"
END FUNCTION
以后在动态生成 Select 语句, 使用:
SqlString = "Select * from myBas where Name = " & CheckString(Text1)
返回
非 DSN 的 ODBC 连接
如果使用 DSN 的话, 每台电脑都要设置 ODBC 连接, 可能还要安装 ODBC 驱动程序。 一旦修改 DSN , 要重新设置每台电脑。 不过, 用了 DSN-Less 连接, 就不需要在每台电脑设置 ODBC 啦。
其实要做的非常简单, 只要修改在连接串中设置 driver 和 server 就 OK。如:
cnstr = "driver={SQL Server}; server=myserver;" & "database=mydb; uid=myuid; pwd=mypwd; dsn=;"
Set cn = en.OpenConnection("", False, False, cnstr)
注意: driver 要用 { },如果使用 DAO 控件, 应该在 Connect 头上增加 "ODBC; "。
返回
建立和删除一个 DSN
1. 增加声明:
Private Const ODBC_ADD_DSN = 1 ' Add data source
Private Const ODBC_CONFIG_DSN = 2 ' Configure (edit) data source
Private Const ODBC_REMOVE_DSN = 3 ' Remove data source
Private Const vbAPINull As Long = 0& ' NULL Pointer
Private Declare Function SQLConfigDataSource Lib "ODBCCP32.DLL" (ByVal hwndParent As Long, ByVal fRequest As Long, ByVal lpszDriver As String, ByVal lpszAttributes As String) As Long
2. 新增加一个 DSN
Dim intRet As Long
Dim strDriver As String
Dim strAttributes As String
'设�