【问题标题】:How to List Field's Name in table in Access Using SQL如何使用 SQL 在 Access 中的表中列出字段的名称
【发布时间】:2012-07-17 22:06:03
【问题描述】:

能否请您告诉我是否可以列出 MS Access 表中的所有字段名称?

【问题讨论】:

  • 既然提到了SQL,也许你想做一些类似SQL Server的事情,比如Select object_Name(object_ID),definition from Pastries.SQL_Modules where object_Name(object_ID)='custard'。我相信 Access 不提供这种对象可见性。

标签: sql ms-access


【解决方案1】:

我在 ms 访问中工作太多了。

我知道这样做的唯一方法是使用 vba,并定义例如记录集,然后遍历字段。

例如:

Sub ListFields()

dim rst as new adodb.recordset
rst.open "SELECT * FROM SomeTable", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
' Note: adOpenForwardOnly and adLockReadOnly are the default values '
' for the CursorType and LockType arguments, so they are optional here '
' and are shown only for completeness '

dim ii as integer
dim ss as string
for ii = 0 to rst.fields.count - 1
    ss = ss & "," & rst.fields(ii).name
next ii

Debug.Print ss

End Sub

字符串变量ss 将包含名为“SomeTable”的表中所有列名的逗号分隔列表。

只要对逻辑进行一点重新格式化,您就可以根据需要将此数据插入到另一个表中,然后进行查询。

这有帮助吗?

【讨论】:

  • 对 SQL 的使用表示支持(也许有点名义上),以及在 MS Access 中工作过多的明确证据。
  • Access 并不总是您需要的工具,但它通常是您拥有的工具。关于在 Access 2013 中应用此功能的一个注意事项:我必须在 Tools -> References 中启用 Microsoft ActiveX Data Objects 6.1 Library 才能解析 ADO 库。
  • @John Bingham - 刚刚被 AccessDB 卡住了,不得不来查一下 - 它让我免于一些恼怒和一些令人沮丧的想法 :) 谢谢!
  • 好,紧凑的方法,谢谢,并且经过测试可以为我工作。我提出了一些额外的行来将这个 VBA 片段转换为一个 sub,使开发人员能够按需获得一次性输出(当然,'SomeTable' 仍然需要替换为正确的表名)。跨度>
【解决方案2】:

此版本易于运行,可直接粘贴到 Access 中。将此函数添加到模块中,按 F5 运行,然后从输入框中复制结果:

Public Function FieldNames() As String

    Dim sTable As String
    Dim rs As DAO.Recordset
    Dim n As Long
    Dim sResult As String

    sTable = InputBox("Name of table?")
    If sTable = "" Then
        Exit Function
    End If

    Set rs = CurrentDb.OpenRecordset(sTable)

    With rs
        For n = 0 To .Fields.Count - 1
            sResult = sResult & .Fields(n).Name & vbCrLf
        Next 'n
        .Close
    End With

    Set rs = Nothing

    InputBox "Result:" & vbCrLf & vbCrLf _
            & "Copy this text (it looks jumbled, but it has one field on each line)", _
            "FieldNames()", sResult

End Function

替代输出:

用户 user1003916 提供了 InputBox 的替代方案来克服 1024 个字符的限制(我还没有测试过):

Sub CopyText(Text As String)

    'VBA Macro using late binding to copy text to clipboard.
    'By Justin Kay, 8/15/2014

    Dim MSForms_DataObject As Object
    Set MSForms_DataObject = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")

    MSForms_DataObject.SetText Text
    MSForms_DataObject.PutInClipboard
    Set MSForms_DataObject = Nothing

End Sub

【讨论】:

  • 效果很好。它列出了您输入的任何表中的所有字段。唯一令人困惑的部分是......它将结果放入那个小文本框中。我认为它不起作用,但它正在起作用。只需将粘贴结果复制到 Excel 或 Notepad++
  • 好点,Shai。我在最后的对话框中添加了一些文本,这样就不会那么混乱了。
  • 很棒的脚本,但请记住这里有 1024 个字符的限制。如果您有很多长列名,它将截断它们。我的表有 255 列,它只占了大约一半。
  • 谢谢@user1003916。我采纳了你的建议。
【解决方案3】:

更新:要使用此 SQL 查询,您必须使用 DBEAVER 等工具。 访问客户端将不允许您查询它的隐藏结构。

哎呀! IMO:我无法想象想要深入 VBA 的阴暗面

如何通过 SQL 获取访问表列

SELECT * FROM information_schema.columns 
    WHERE TABLE_NAME="YOUR_TABLE_NAME" 
       AND 
    TABLE_SCHEMA="PUBLIC" 

PS 我注意到 Access 将我的架构称为“PUBLIC”

上面使用了 Access 2016,并通过 ODBC 和 jdbc:ucanaccess 进行了测试,效果非常好。

示例输出

【讨论】:

  • 不知道为什么这个想法被否决了。该技术效果很好。
  • 我用我的表名等将它弹出到一个查询窗口中,它说找不到文件 information_scheme.mdb
  • 很抱歉,我似乎忘记了一项基本说明。您不能使用 Access 客户端对 Access 数据库执行此查询。相反,您必须使用 DBeaver 等工具。我不知道为什么,但是当查询在 Access 中运行时,一切都变得松散了。当在 dBeaver 中运行相同的查询时,您会得到预期的结果
  • 请重新阅读我的说明,我已尝试提供一个清晰的示例,如何使用纯 sql 从 access 数据库中实现列名。
  • 我没有给你投反对票。我只是在回复 btw :) 看起来是个不错的工具
【解决方案4】:

您可以简单地使用 Documenter 工具。转到Database Tools > Database Documenter,选择表格并按确定。

【讨论】:

  • 我只能同意你的看法。无论如何,感觉答案可能会有所帮助。可能不是最好的想法。
  • 我认为这不是最好的问题:)
  • 虽然这行得通,但它可能是你能得到的最没有帮助的格式。
【解决方案5】:

一种快速而肮脏的方法涉及 Excel。执行以下操作:

  1. 在数据表视图中打开表格。
  2. 使用适用于您的 Access 版本的特定过程导出到 Excel 文件。
  3. 打开 Excel 文件(如果尚未打开)。
  4. 选择并复制包含标题的第一行。
  5. 向工作簿添加另一个工作表(如果不存在)。
  6. 点击 A1。
  7. 选择性粘贴>转置

字段将粘贴在单个列中。要找出它们的字段索引号,请在单元格 B1 中输入“0”,然后依次填写字段编号的最后一行。

此外,您可以按字母顺序对列进行排序,尤其是对于涉及数十个字段的旧版平面文件。当我尝试将平面文件转换为关系模型时,这确实节省了很多时间。

【讨论】:

  • 然后粘贴到 VSCode 或类似代码中,根据需要添加逗号、引号等。
【解决方案6】:

已经有一些很好的答案,但我决定添加我自己的转折。希望它们是不言自明的。

用法:

  • getFieldNames(TableName:="Table1",IncludeBrackets:=True,Delimiter:=vbNewLine,CopyToClipboard:=True)
  • getFieldNames(TableName:="Table1",IncludeBrackets:=True,CopyToClipboard:=True)
  • getFieldNames(TableName:="Table1",IncludeBrackets:=True)
  • getFieldNames(TableName:="Table1")

我用它来构建一个字段名数组:

  • Chr(34) & getFieldNames(TableName:="Table1",IncludeBrackets:=False, Delimiter:= Chr(34) & "," & Chr(34)) & Chr(34)

Function getFieldNames(ByVal TableName As String, Optional ByVal IncludeBrackets As Boolean, Optional ByVal Delimiter As String = ", ", Optional ByVal CopyToClipboard As Boolean) As String
    Dim rs As DAO.Recordset

    On Error Resume Next
    Set rs = CurrentDb.OpenRecordset(TableName)
    On Error GoTo 0

    If rs Is Nothing Then Exit Function

    Dim results() As String
    ReDim results(rs.Fields.Count - 1)

    Dim n As Long
    For n = 0 To rs.Fields.Count - 1
        results(n) = rs.Fields(n).Name
    Next
    rs.Close

    Dim result As String
    If IncludeBrackets Then
        result = "[" & Join(results, "]" & Delimiter & "[") & "]"
    Else
        result = Join(results, Delimiter)
    End If


    If CopyToClipboard Then
        With CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
            .SetText result
            .PutInClipboard
        End With
    End If

    getFieldNames = result
End Function

【讨论】:

    【解决方案7】:

    这不是 SQL,但对于像我这样只需要列出查询选择所需的字段名称的人来说,这个问题是最重要的 Google 结果,因为 Access 不支持 "* except foo, bar" 来获得 99表格的百分比。

    答案改编自 Patrick Wood,Access MVP 的 social.msdn.com 回答 https://social.msdn.microsoft.com/Forums/office/en-US/1fe5546b-db3f-4e17-9bf8-04f4dee233b7/how-to-list-all-the-field-names-in-a-specified-table?forum=accessdev

    在模块中将 tablename 更改为您的名称。这个函数应该是全局级别的:

    Function ListTdfFields()
        ' NOT doing DIMs, since then you must enable/attach ADODB or DAO
        ' Dim db As ADO.Database
        Set db = CurrentDb
        tablename = "tblProductLicense"  ' <=== YOUR TABLE NAME HERE
        Set tdf = db.TableDefs(tablename)
        For Each fld In tdf.Fields
            Debug.Print tablename; ".["; fld.Name; "]," ; 
            ' remove ending ; for 1 line per field
        Next
        Debug.Print ""
        Set tdf = Nothing
        Set db = Nothing
    End Function
    

    然后添加一个宏 RunCode ListTdfFields() 并运行它。输出将被发送到模块的 VBA 设计视图的即时窗口。

    【讨论】:

      【解决方案8】:

      我想分享这个 VBA 解决方案,我没有写,只是稍作修改(将 tableName 更改为使用 'SourceTable')。运行后,您可以查询它创建的表。它利用了隐藏的系统表。

      Sub GetField2Description()
      '************************************************* *********
      'Purpose: 1) Deletes and recreates a table (tblFields)
      ' 2) Queries table MSysObjects to return names of
      ' all tables in the database
      ' 3) Populates tblFields
      'Coded by: raskew
      'Inputs: From debug window:
      ' Call GetField2Description
      'Output: See tblFields
      '************************************************* *********
      Dim db As DAO.Database, td As TableDef
      Dim rs As Recordset, rs2 As Recordset
      Dim Test As String, NameHold As String
      Dim typehold As String, SizeHold As String
      Dim fielddescription As String, tName As String
      Dim n As Long, i As Long
      Dim fld As Field, strSQL As String
      n = 0
      Set db = CurrentDb
      ' Trap for any errors.
      On Error Resume Next
      tName = "tblFields"
      'Does table "tblFields" exist? If true, delete it;
      DoCmd.SetWarnings False
      DoCmd.DeleteObject acTable, "tblFields"
      DoCmd.SetWarnings True
      'End If
      'Create new tblTable
          db.Execute     "CREATE TABLE tblFields(Object TEXT (55), FieldName TEXT (55),     FieldType TEXT (20), FieldSize Long, FieldAttributes Long, FldDescription TEXT (20));"
      strSQL = "SELECT MSysObjects.Name, MSysObjects.Type From MsysObjects WHERE"
      strSQL = strSQL + "((MSysObjects.Type)=1)"
      strSQL = strSQL + "ORDER BY MSysObjects.Name;"
      Set rs = db.OpenRecordset(strSQL)
      If Not rs.BOF Then
      ' Get number of records in recordset
      rs.MoveLast
      n = rs.RecordCount
      rs.MoveFirst
      End If
      Set rs2 = db.OpenRecordset("tblFields")
      For i = 0 To n - 1
      fielddescription = " "
      Set td = db.TableDefs(i)
      'Skip over any MSys objects
      If Left(rs!Name, 4) <> "MSys" And Left(rs!Name, 1) <> "~" Then
      NameHold = rs!Name
      On Error Resume Next
      For Each fld In td.Fields
      tableName = fld.SourceTable
      
      fielddescription = fld.Name
      typehold = FieldType(fld.Type)
      SizeHold = fld.Size
      rs2.AddNew
      rs2!Object = tableName
      rs2!FieldName = fielddescription
      rs2!FieldType = typehold
      rs2!FieldSize = SizeHold
      rs2!FieldAttributes = fld.Attributes
      rs2!FldDescription = fld.Properties("description")
      rs2.Update
      Next fld
      Resume Next
      End If
      rs.MoveNext
      Next i
      rs.Close
      rs2.Close
      db.Close
      End Sub
      Function FieldType(intType As Integer) As String
      Select Case intType
      Case dbBoolean
      FieldType = "dbBoolean" '1
      Case dbByte
      FieldType = "dbByte" '2
      Case dbInteger
      FieldType = "dbInteger" '3
      Case dbLong
      FieldType = "dbLong" '4
      Case dbCurrency
      FieldType = "dbCurrency" '5
      Case dbSingle
      FieldType = "dbSingle" '6
      Case dbDouble
      FieldType = "dbDouble" '7
      Case dbDate
      FieldType = "dbDate" '8
      Case dbBinary
      FieldType = "dbBinary" '9
      Case dbText
      FieldType = "dbText" '10
      Case dbLongBinary
      FieldType = "dbLongBinary" '11
      Case dbMemo
      FieldType = "dbMemo" '12
      Case dbGUID
      FieldType = "dbGUID" '15
      End Select
      End Function
      

      【讨论】:

        【解决方案9】:

        构建查询:

        SELECT Table_Name.*
        FROM Table_Name
        WHERE False;
        

        导出到 Excel 您将在没有任何数据的情况下将每个字段名称放在一行中。如果选择行并复制,则可以粘贴特殊>转置并将它们全部放在一个列中。

        【讨论】:

        • 在检查 Stack Overflow 之前,我基本上尝试了这种方法。不幸的是,有人(将保持匿名)在许多字段上设置了标题,结果证明复制和粘贴是失败的。只有化妆品版本会进入剪贴板。
        【解决方案10】:

        此 SQL 在 Access 2016 中适用于查询,而不是表,但可能有用。

        SELECT MSysObjects.Name AS QueryName, 
               IIf(IsNull([Name1]),
                   Right([Expression],Len([Expression])-InStr(1,[Expression],".")),[name1])
                   AS FieldName
          FROM MSysQueries INNER JOIN MSysObjects 
            ON MSysQueries.ObjectId = MSysObjects.Id
         WHERE MSysQueries.Attribute=6;
        

        【讨论】:

          【解决方案11】:

          我来这里是为了寻找相同的要求,在参考了这个帖子之后,为我的要求起草了下面的代码。源表中的字段名称将被添加到一个数组中,稍后字段名称将分配给第二个表。只是在这里分享一下,这可能对以后有帮助..

          Public Sub FieldName_Change()
          Dim intNumberOfFields, intX As Integer
          Dim txtTableName,txttmpTableName txtFieldName() As String
          
          intNumberOfFields = GetFieldNames(txtTableName, txtFieldName())
          For intX = 1 To intNumberOfFields
            CurrentDb.TableDefs(txttmpTableName).Fields("F" & intX).Name = txtFieldName(intX)
          Next intX
          End Sub
          
          
          Public Function GetFieldNames(ByVal txtTableName As String, ByRef txtFiledName() As String) As Integer
          Dim rs As DAO.Recordset
          Dim n As Long
          Dim sResult As String
          
          Set rs = CurrentDb.OpenRecordset(txtTableName)
          ReDim txtFiledName(rs.Fields.Count)
          With rs
              For n = 0 To .Fields.Count - 1
                  txtFiledName(n + 1) = .Fields(n).Name
              Next n
              .Close
              GetFieldNames = n
          End With
          Set rs = Nothing
          End Function
          

          【讨论】:

            【解决方案12】:

            在过去,这项任务似乎更容易。这个答案可能高度依赖于版本。它适用于我对 Access 2007 DB 的快速测试:

            select 
            Specs.SpecName AS TableName,
            Columns.FieldName
            from
            MSysIMEXColumns Columns
            inner join MSysIMEXSpecs Specs on Specs.SpecID = Columns.SpecID
            order by
            Specs.SpecName,
            Columns.FieldName
            

            【讨论】:

            • 啊,我可能被我的结果愚弄了,因为我在我正在查看的表上设置了导入规范。就像我说的,在过去似乎这项任务更容易。哦,好吧。
            • 这仅列出了导入链接规范,而不是表字段。
            【解决方案13】:

            试一试...

                private void Button_OldDDLDump_Click(object sender, EventArgs e)
                {
                    string _cnstr = "connectionstringhere";
                    OleDbConnection _cn = new OleDbConnection(_cnstr);
                    try
                    {
                        _cn.Open();
                        System.Data.DataTable _dt = null;            
                        try
                        {
                            _dt = _cn.GetSchema("tables");
                            m_msghelper.AppendArray( DataTableHelper.DataTableToString(_dt) );                               
                        }
                        catch (Exception _ex)
                        {
                            System.Diagnostics.Debug.WriteLine(_ex.ToString());
                        }
                        finally
                        {
                            _dt.Dispose();
                        }
                    }
                    catch (Exception _ex)
                    {
                        System.Diagnostics.Debug.WriteLine(_ex.ToString());
                    }
                    finally
                    {
                        _cn.Close();
                    }
                }
            

            帮助方法在这里将数据库结构转储到字符串数组..

            public static class DataTableHelper
            {
                public static string[] DataTableToString( System.Data.DataTable dt )
                {
                    List<string> _retval = new List<string>();
            
                    foreach (System.Data.DataRow row in dt.Rows)
                    {
                        foreach (System.Data.DataColumn col in dt.Columns)
                        {
                            _retval.Add( string.Format("{0} = {1}", col.ColumnName, row[col]) );
                        }
                        _retval.Add( "============================");
                    }
                    return _retval.ToArray();
                }
            }
            

            【讨论】:

              【解决方案14】:

              从 information_schema.columns where table_name='table' 中选择 column_name

              【讨论】:

              • 这不起作用。这适用于 MS SQL 或 MySQL,但不适用于 Access。如果这可行,那就太棒了。
              猜你喜欢
              • 1970-01-01
              • 2023-04-03
              • 2015-06-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多