Sql 检查访问表是否存在
我想记录网站访问的IP、datetime、客户端和引用方数据以访问数据库,但我计划每天在单独的表中记录日志数据,例如,2010年6月6日的日志将记录在2010年6月6日命名的表中。更改日期后,我将创建一个名为2010_06_07的表。但问题是这个表是否已经创建Sql 检查访问表是否存在,sql,ms-access,ms-access-2007,Sql,Ms Access,Ms Access 2007,我想记录网站访问的IP、datetime、客户端和引用方数据以访问数据库,但我计划每天在单独的表中记录日志数据,例如,2010年6月6日的日志将记录在2010年6月6日命名的表中。更改日期后,我将创建一个名为2010_06_07的表。但问题是这个表是否已经创建 有没有关于如何检查Access中是否存在表的建议?这里有另一个解决方案,它比在所有表上循环要快一点 Public Function doesTableExist(strTableName As String) As Boolean
有没有关于如何检查Access中是否存在表的建议?这里有另一个解决方案,它比在所有表上循环要快一点
Public Function doesTableExist(strTableName As String) As Boolean
Dim db As DAO.Database
Dim td As DAO.TableDef
Set db = CurrentDb
On Error Resume Next
Set td = db.TableDefs(strTableName)
doesTableExist = (Err.Number = 0)
Err.Clear
End Function
您可以使用隐藏的系统表MSysObjects检查表是否存在:
If Not IsNull(DlookUp("Name","MSysObjects","Name='TableName'")) Then
'Table Exists
然而,我同意每天创建一个新表是一个非常糟糕的想法
编辑:我应该补充一点,表的类型为1、4或6,不同类型的其他对象可能与表同名,因此最好说:
If Not IsNull(DlookUp("Name","MSysObjects","Name='TableName' And Type In (1,4,6)")) Then
'Table Exists
但是,不可能创建与查询同名的表,因此如果需要查找以测试名称,最好在类型列表中添加5个,即查询。几年前,我测试了各种方法来确定表是否存在。下面是我实现的所有这些代码,包括我的简单测试例程
Public Function TableExists(strTableName As String, Optional ysnRefresh As Boolean, Optional db As DAO.Database) As Boolean
' Originally Based on Tony Toews function in TempTables.MDB, http://www.granite.ab.ca/access/temptables.htm
' Based on testing, when passed an existing database variable, this is the fastest
On Error GoTo errHandler
Dim tdf As DAO.TableDef
If db Is Nothing Then Set db = CurrentDb()
If ysnRefresh Then db.TableDefs.Refresh
Set tdf = db(strTableName)
TableExists = True
exitRoutine:
Set tdf = Nothing
Exit Function
errHandler:
Select Case Err.Number
Case 3265
TableExists = False
Case Else
MsgBox Err.Number & ": " & Err.Description, vbCritical, "Error in mdlBackup.TableExists()"
End Select
Resume exitRoutine
End Function
Public Function TableExists2(strTableName As String, Optional ysnRefresh As Boolean, Optional db As DAO.Database) As Boolean
On Error GoTo errHandler
Dim bolCleanupDB As Boolean
Dim tdf As DAO.TableDef
If db Is Nothing Then
Set db = CurrentDb()
bolCleanupDB = True
End If
If ysnRefresh Then db.TableDefs.Refresh
For Each tdf In db.TableDefs
If tdf.name = strTableName Then
TableExists2 = True
Exit For
End If
Next tdf
exitRoutine:
Set tdf = Nothing
If bolCleanupDB Then
Set db = Nothing
End If
Exit Function
errHandler:
MsgBox Err.Number & ": " & Err.Description, vbCritical, "Error in mdlBackup.TableExists1()"
Resume exitRoutine
End Function
Public Function TableExists3(strTableName As String, _
Optional db As DAO.Database) As Boolean
' Based on testing, when NOT passed an existing database variable, this is the fastest
On Error GoTo errHandler
Dim strSQL As String
Dim rs As DAO.Recordset
If db Is Nothing Then Set db = CurrentDb()
strSQL = "SELECT MSysObjects.Name FROM MSysObjects "
strSQL = strSQL & "WHERE MSysObjects.Name=" & Chr(34) & strTableName & Chr(34)
strSQL = strSQL & " AND MSysObjects.Type=6;"
Set rs = db.OpenRecordset(strSQL)
TableExists3 = (rs.RecordCount <> 0)
exitRoutine:
If Not (rs Is Nothing) Then
rs.Close
Set rs = Nothing
End If
Exit Function
errHandler:
MsgBox Err.Number & ": " & Err.Description, vbCritical, _
"Error in TableExists1()"
Resume exitRoutine
End Function
Public Sub TestTableExists(strTableName As String, intLoopCount As Integer)
Dim dteStart As Date
Dim i As Integer
Dim bolResults As Boolean
dteStart = Now()
For i = 0 To intLoopCount
bolResults = TableExists(strTableName, , CurrentDB())
Next i
Debug.Print "TableExists (" & intLoopCount & "): " & Format(Now() - dteStart, "nn:ss")
dteStart = Now()
For i = 0 To intLoopCount
bolResults = TableExists2(strTableName, , CurrentDB())
Next i
Debug.Print "TableExists2 (" & intLoopCount & "): " & Format(Now() - dteStart, "nn:ss")
dteStart = Now()
For i = 0 To intLoopCount
bolResults = TableExists3(strTableName, CurrentDB())
Next i
Debug.Print "TableExists3 (" & intLoopCount & "): " & Format(Now() - dteStart, "nn:ss")
End Sub
Public Function TableExists(strTableName为字符串,可选ysnRefresh为布尔值,可选db为DAO.Database)为布尔值
'最初基于Telletables.MDB中的Tony Toews函数,http://www.granite.ab.ca/access/temptables.htm
'根据测试,当传递现有数据库变量时,这是最快的
关于错误转到错误处理程序
将tdf调暗为DAO.TableDef
如果db为空,则设置db=CurrentDb()
如果为ysnRefresh,则为db.TableDefs.Refresh
设置tdf=db(strTableName)
TableExists=True
现存的:
设置tdf=无
退出功能
错误处理程序:
选择案例错误编号
案例3265
TableExists=False
其他情况
MsgBox Err.Number&“:”&Err.Description,vbCritical,“mdlBackup.TableExists()中的错误”
结束选择
恢复原状
端函数
公共函数TableExists2(strTableName为字符串,可选ysnRefresh为布尔值,可选db为DAO.Database)为布尔值
关于错误转到错误处理程序
将bolCleanupDB设置为布尔值
将tdf调暗为DAO.TableDef
如果db什么都不是,那么
Set db=CurrentDb()
bolCleanupDB=True
如果结束
如果为ysnRefresh,则为db.TableDefs.Refresh
对于以db.TableDefs为单位的每个tdf
如果tdf.name=strTableName,则
TableExists2=True
退出
如果结束
下一个tdf
现存的:
设置tdf=无
如果是bolCleanupDB,那么
Set db=Nothing
如果结束
退出功能
错误处理程序:
MsgBox错误号&“:”错误描述,vbCritical,“mdlBackup.TableExists1()中的错误”
恢复原状
端函数
公共函数TableExists3(strTableName作为字符串_
可选数据库(作为DAO.Database)作为布尔值
'根据测试,当未传递现有数据库变量时,这是最快的
关于错误转到错误处理程序
作为字符串的Dim strSQL
Dim rs作为DAO.Recordset
如果db为空,则设置db=CurrentDb()
strSQL=“从MSysObjects中选择MSysObjects.Name”
strSQL=strSQL&“其中MSysObjects.Name=“&Chr(34)&strTableName&Chr(34)
strSQL=strSQL&“和MSysObjects.Type=6;”
Set rs=db.OpenRecordset(strSQL)
TableExists3=(rs.RecordCount 0)
现存的:
如果不是(rs什么都不是),那么
rs.Close
设置rs=无
如果结束
退出功能
错误处理程序:
MsgBox错误编号&“:”&错误说明,vbCritical_
“TableExists1()中出现错误”
恢复原状
端函数
公共子TestTableExists(strTableName为字符串,intLoopCount为整数)
Dim dteStart As Date
作为整数的Dim i
将结果设置为布尔值
dteStart=Now()
对于i=0到intLoopCount
bolResults=TableExists(strTableName,CurrentDB())
接下来我
Debug.Print“TableExists(&intLoopCount&)”:&Format(现在()-dteStart,“nn:ss”)
dteStart=Now()
对于i=0到intLoopCount
bolResults=TableExists2(strTableName,CurrentDB())
接下来我
Debug.Print“TableExists2(&intLoopCount&)”:&Format(Now()-dteStart,“nn:ss”)
dteStart=Now()
对于i=0到intLoopCount
bolResults=TableExists3(strTableName,CurrentDB())
接下来我
Debug.Print“TableExists3(&intLoopCount&)”:&Format(Now()-dteStart,“nn:ss”)
端接头
我发现查询系统表或TableDef是不可靠的,并且在脚本中引入了不可预测的行为,在脚本中经常创建和删除表
根据我的结果,我的假设是,这些表不一定在执行CREATE
或DROP
时更新,或者并发性问题阻碍了我获得准确的结果
我发现以下方法更可靠:
公共函数表存在(数据库为Access.Application_
tableName(作为字符串)作为布尔值
'假定该表不存在。
TableExists=False
'定义迭代器以查询对象模型。
可调为整数
'循环浏览对象目录并与搜索词进行比较。
对于iTable=0,请访问database.CurrentData.AllTables.Count-1
如果database.CurrentData.AllTables(iTable).Name=tableName,则
TableExists=True
退出功能
如果结束
下一个
端函数
除非有惊人数量的表集合,否则迭代应该没有运行时问题。这个问题很老了,但我发现没有一个答案是令人满意的,因为:
- 它们不处理“坏”链接表的情况,即链接表指向不存在的db或表李>
- 由于链接表可能很大,我们必须能够用快速查询来检查它们
Function isTableOk(tblName As String) As Boolean
'works with local or linked tables
Dim db As DAO.Database, rs As DAO.Recordset
Dim sSql As String
sSql = "SELECT TOP 1 ""xxx"" AS Expr1 FROM [" & tblName & "]"
On Error Resume Next
Err.Clear
Set db = CurrentDb
Set rs = db.OpenRecordset(sSql)
isTableOk = (Err.Number = 0)
rs.Close
End Function
您甚至可以使用以下版本在外部访问数据库中检查表:
Function isTableOk(tblName As String, Optional dbName As String) As Boolean
'works with local or linked tables, or even tables in external db (if dbName is provided)
Dim db As DAO.Database, rs As DAO.Recordset
Dim sSql As String
Set db = CurrentDb
sSql = "SELECT TOP 1 'xxx' AS Expr1 FROM [" & tblName & "]"
If Len(dbName) > 0 Then 'external db
sSql = sSql & " IN '" & dbName & "'"
End If
Err.Clear
On Error Resume Next
Set rs = db.OpenRecordset(sSql)
isTableOk = (Err.Number = 0)
rs.Close
End Function
您可能需要考虑使用一个表,然后使用参数化查询生成