我想记录网站访问的IP,日期时间,客户端和refferer数据来访问数据库但我计划每天记录日志数据在06.06.2010的示例日志中的单独表中将记录在2010_06_06命名表中。当日期改变时,我将创建一个名为2010_06_07的表。但问题是如果已经创建了这个表。
如何检查Access中是否存在表格的任何建议?
答案 0 :(得分:36)
您可以使用隐藏的系统表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(即查询)添加到“类型”列表中
答案 1 :(得分:7)
我测试了各种方法,以确定几年前是否存在表格。以下是我实现的所有代码,包括我的简单测试例程。
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
答案 2 :(得分:6)
这是另一种解决方案,比循环遍历所有表格要快一些。
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
答案 3 :(得分:2)
我发现查询系统表或tabledef是不可靠的,并在脚本中引入不可预测的行为,其中表会定期创建和删除。
根据我的结果,我的假设是这些表格不一定在执行CREATE
或DROP
的确切时刻更新,或者并发问题阻止我获得准确的结果。
我发现以下方法更可靠:
Public Function TableExists(theDatabase As Access.Application, _
tableName As String) As Boolean
' Presume that table does not exist.
TableExists = False
' Define iterator to query the object model.
Dim iTable As Integer
' Loop through object catalogue and compare with search term.
For iTable = 0 To theDatabase.CurrentData.AllTables.Count - 1
If theDatabase.CurrentData.AllTables(iTable).Name = tableName Then
TableExists = True
Exit Function
End If
Next iTable
End Function
除非有庞大的表集合,否则不应该迭代运行时问题。
答案 4 :(得分:1)
这个问题已经很老了,但是我发现没有令人满意的答案,因为:
这是我简单但更完整的解决方案:
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
您甚至可以使用以下版本检查外部 Access数据库中的表:
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