【问题标题】:Retrieve list of indexes in an Access database检索 Access 数据库中的索引列表
【发布时间】:2010-03-29 09:43:54
【问题描述】:

我知道有一种方法可以通过查询 MsysObjects 来获取 Access 数据库中所有表的列表:

SELECT MSysObjects.Name FROM MsysObjects
WHERE
  Left$([Name],1)<>'~' AND
  Left$([Name],4)<>'Msys' AND
  MSysObjects.Type=1

有人知道类似(或其他)方法来检索 MS-Access 数据库中所有索引的列表吗?

【问题讨论】:

    标签: database ms-access ms-access-2007


    【解决方案1】:

    您可以检查TableDef 对象以访问索引名称。

    Public Sub ShowIndexNames()
        Dim tdf As TableDef
        Dim idx As Index
        Dim num_indexes As Long
    
    On Error GoTo ErrorHandler
    
        For Each tdf In CurrentDb.TableDefs
            num_indexes = tdf.Indexes.Count
            If Left$(tdf.Name, 4) <> "MSys" Then
                If num_indexes > 0 Then
                    For Each idx In tdf.Indexes
                        Debug.Print tdf.Name, idx.Name
                    Next idx
                End If
             End If
        Next tdf
    
    ExitHere:
        Exit Sub
    
    ErrorHandler:
        Select Case Err.Number
        Case 3110
            'Could not read definitions; no read definitions '
            'permission for table or query '<Name>'. '
            Debug.Print "No read definitions permission for " _
                & tdf.Name
            num_indexes = 0
            Resume Next
        Case Else
            Debug.Print Err.Number & "-> " & Err.Description
            GoTo ExitHere
        End Select
    End Sub
    

    编辑:修改 sub 以忽略 MSys*(访问系统)表。

    您还可以使用 ADO 的 OpenSchema 方法来检索有关索引的信息。下面的代码列出了索引名称、关联表以及索引是否为主键。我编写它是为了对 ADO 使用后期绑定,因为这不需要为 Microsoft ActiveX Data Objects [version] Library 设置引用。

    Const adSchemaIndexes As Long = 12
    Dim cn As Object ' ADODB.Connection
    Dim rs As Object ' ADODB.Recordset
    Dim i As Long
    
    Set cn = CurrentProject.Connection
    Set rs = cn.OpenSchema(adSchemaIndexes)
    With rs
        ' enable next three lines to view all the recordset column names
    '    For i = 0 To (.Fields.Count - 1)
    '        Debug.Print .Fields(i).Name
    '    Next i
        Do While Not .EOF
           Debug.Print !TABLE_NAME, !INDEX_NAME, !PRIMARY_KEY
           .MoveNext
        Loop
        .Close
    End With
    Set rs = Nothing
    Set cn = Nothing
    

    如果您更喜欢检查单个表的索引而不是数据库中的每个表,请将表名作为数组的第五个元素传递。

    Set rs = cn.OpenSchema(adSchemaIndexes, Array(Empty, Empty, Empty, Empty, "tblFoo"))
    

    【讨论】:

      【解决方案2】:

      如果您需要使用 .Net OleDb 提供程序而仅此而已

      DataTable indexes = 
      (myOleDbConnection.GetOleDbSchemaTable(
      System.Data.OleDb.OleDbSchemaGuid.Indexes,
      new object[] { null, null, null, null, tableName});
      

      (指定正确的连接和正确的表)。

      在索引 DataTable 中,您可以同时拥有索引和字段。

      【讨论】:

        【解决方案3】:

        扩充至HansUp's answer。

        除了知道索引的名称之外,了解这些索引中引用了哪些字段几乎总是必不可少的。例如,将表从访问数据库导入 SQL Server 2008 R2 时,它不会复制键和索引,因此我需要重新生成它们。到目前为止,该脚本不能正确处理外键约束,但应该生成主键以及标准索引。我会在 FK 问题排序后对其进行编辑。

        Public Sub Generate_tSQLIndex()
            Dim tdf As TableDef
            Dim fld As DAO.Field
            Dim idx As Index
            Dim num_indexes As Long
            Dim indexdef_tsql As String
            Dim pk As Boolean
            On Error GoTo ErrorHandler
            For Each tdf In CurrentDb.TableDefs
                num_indexes = tdf.Indexes.Count
                If Left$(tdf.Name, 4) <> "MSys" Then
                    If num_indexes > 0 Then
                        For Each idx In tdf.Indexes
                            pk = idx.Primary
                            If pk Then indexdef_tsql = "ALTER TABLE [" + tdf.Name + "] WITH CHECK ADD CONSTRAINT [PK_" + tdf.Name + "_" + idx.Name + "] PRIMARY KEY " Else indexdef_tsql = "CREATE "
                            If idx.Unique And Not pk Then indexdef_tsql = indexdef_tsql + "UNIQUE "
                            If idx.Clustered Then indexdef_tsql = indexdef_tsql + "CLUSTERED " Else indexdef_tsql = indexdef_tsql + "NONCLUSTERED "
                            If Not pk Then indexdef_tsql = indexdef_tsql + "INDEX [" + idx.Name + "] ON [" + tdf.Name + "] "
                            indexdef_tsql = indexdef_tsql + "("
                            For Each fld In idx.Fields
                                indexdef_tsql = indexdef_tsql + "[" + fld.Name + "]"
                                If fld.Attributes = 1 Then indexdef_tsql = indexdef_tsql + " DESC, " Else indexdef_tsql = indexdef_tsql + " ASC, "
                            Next fld
                            If idx.Fields.Count > 0 Then indexdef_tsql = Left(indexdef_tsql, Len(indexdef_tsql) - 2)
                            indexdef_tsql = indexdef_tsql + ")"
                            Debug.Print indexdef_tsql
                        Next idx
                    End If
                 End If
            Next tdf
        
        ExitHere:
                Exit Sub
        
        ErrorHandler:
            Select Case Err.Number
                Case 3110
                'Could not read definitions; no read definitions '
                'permission for table or query '<Name>'. '
                Debug.Print "No read definitions permission for " + tdf.Name
                num_indexes = 0
                Resume Next
            Case Else
                Debug.Print Err.Number & "-> " & Err.Description
                GoTo ExitHere
            End Select
            
        End Sub
        

        【讨论】:

        • 谢谢你。很有用。您需要添加一个额外的行 Dim fld As DAO.Field
        猜你喜欢
        • 2012-11-11
        • 1970-01-01
        • 1970-01-01
        • 2017-08-17
        • 1970-01-01
        • 2018-12-14
        • 1970-01-01
        • 2023-04-04
        • 2011-06-23
        相关资源
        最近更新 更多