简体   繁体   English

使用SQL和VB6将XML数据导入MS Access表

[英]Import XML data into MS Access table Using SQL and VB6

I have an XML file with many records down under "/response/result/record". 我有一个XML文件,其中很多记录都位于“ / response / result / record”下。 For example: 例如:

<response>
  <result>
    <record>
      <flda>some text</flda>
      <fldb>some text</fldb>
      :     :     :
    </record>
    :    :    :
  </result>
</response>

I have an MSAccess database and a legacy VB6 program that needs to read this file and load it into a table containing a field for each text node in each record. 我有一个MSAccess数据库和一个旧版VB6程序,需要读取该文件并将其加载到包含每个记录中每个文本节点字段的表中。

I know I can use MSXML2.DOMDocument to Load the XML from the internet and possibly save it to a file. 我知道我可以使用MSXML2.DOMDocument从Internet加载XML并将其保存到文件中。 I can also then use the DOMDocument to read the XML and load the MSAccess database table one record at a time. 然后,我还可以使用DOMDocument读取XML并一次将一条记录加载到MSAccess数据库表中。

This seems inefficient, since I can load CSV files into an MSAccess table using VB6 syntax such as: 这似乎效率很低,因为我可以使用VB6语法将CSV文件加载到MSAccess表中,例如:

db.Execute "Select * Into CSVtable From [Text;FMT=CSVDelimited;HDR=YES;DATABASE=dirPath].[filename]"

And it will quickly bulk load that data into the database. 并且它将迅速将该数据批量加载到数据库中。 Much, much faster than reading each record from the CSV file and using a DAO recordset to add each record one at a time. 比从CSV文件中读取每条记录并使用DAO记录集一次添加每条记录要快得多。

My question : can I do the same thing with an XML file? 我的问题 :我可以对XML文件做同样的事情吗? What is the syntax and how do I do it? 语法是什么,我该怎么做?

Follow-up question : Where do I find documentation on this funky 'Select...' syntax that I show above for CSV files (that I originally found on StackOverflow)? 后续问题 :在哪里可以找到上面显示的CSV文件(最初在StackOverflow上找到的)这种“ Select ...”语法的文档?

The SELECT syntax that you want is defined only in the JETSQL40.CHM document as far as I can determine. 据我所知,仅在JETSQL40.CHM文档中定义了所需的SELECT语法。 This is normally installed with MS Office 2000 or later, but you'll have to dig around in the "Program Files" special folder to find it. 它通常随MS Office 2000或更高版本一起安装,但是您必须在“ Program Files”特殊文件夹中进行查找才能找到它。 There is enough useful stuff there that I usually create a shortcut to it myself. 那里有很多有用的东西,我通常会自己创建一个快捷方式。

However since there is no Jet XML Installable ISAM (IISAM) you would have to do the sort of thing that MS Access does itself to import XML format data. 但是,由于没有Jet XML可安装的ISAM (IISAM),因此您必须做MS Access自己做的事情来导入XML格式数据。

While that does involve looping, you can do your bulk insert in a more optimal manner than people commonly do. 尽管这确实涉及循环,但是您可以以比一般人更好的最佳方式来进行批量插入。 The code used below attempts to do that. 下面使用的代码试图做到这一点。

This program has a Form with a single Menu item mnuImportXML and an MSHFlexGrid named FlexGrid to display the contents of a "Records" table in the database it creates on first run: 该程序具有一个带有单个菜单项mnuImportXML的窗体,以及一个名为FlexGrid的MSHFlexGrid,用于显示其在首次运行时创建的数据库中“记录”表的内容:

Option Explicit

Private Const CONNWG As String = "Provider=Microsoft.Jet.OLEDB.4.0;" _
                               & "Jet OLEDB:Engine Type=5;" _
                               & "Jet OLEDB:Create System Database=True;" _
                               & "Data Source='$DB$.mdw';"
Private Const CONNDB As String = "Provider=Microsoft.Jet.OLEDB.4.0;" _
                               & "Jet OLEDB:Engine Type=5;" _
                               & "Jet OLEDB:System Database='$DB$.mdw';" _
                               & "Data Source='$DB$.mdb';"

Private CN As ADODB.Connection
Private QueryRS As ADODB.Recordset
Private UpdateRS As ADODB.Recordset
Private XmlRS As ADODB.Recordset
Private recordsRS As ADODB.Recordset
Private AppendFields As Variant

Public Function OpenConnection(ByVal DbPath As String) As ADODB.Connection
    Dim ExtensionPos As Long

    ExtensionPos = InStrRev(DbPath, ".")
    If ExtensionPos > 0 Then DbPath = Left$(DbPath, ExtensionPos - 1)
    On Error Resume Next
    GetAttr DbPath & ".mdb"
    If Err Then
        On Error GoTo 0
        Set OpenConnection = CreateDB(DbPath)
    Else
        On Error GoTo 0
        Set OpenConnection = New ADODB.Connection
        OpenConnection.Open Replace$(CONNDB, "$DB$", DbPath)
    End If
End Function

Private Function CreateDB(ByVal DbPath As String) As ADODB.Connection
    Dim catDB As Object 'Don't early-bind ADOX objects.

    Set catDB = CreateObject("ADOX.Catalog")
    With catDB
        .Create Replace$(CONNWG, "$DB$", DbPath)
        .Create Replace$(CONNDB, "$DB$", DbPath)
        Set CreateDB = .ActiveConnection
        Set catDB = Nothing
    End With
    With CreateDB
        .Execute "CREATE TABLE [Records](" _
               & "[ID] IDENTITY CONSTRAINT PK_UID PRIMARY KEY," _
               & "[flda] TEXT(255) WITH COMPRESSION," _
               & "[fldb] TEXT(255) WITH COMPRESSION)", , _
                 adCmdText Or adExecuteNoRecords
    End With
End Function

Private Sub RefreshGrid()
    QueryRS.Open "[Records]", , , adLockReadOnly, adCmdTable
    Set FlexGrid.DataSource = QueryRS
    QueryRS.Close
End Sub

Private Sub Form_Load()
    Set CN = OpenConnection("demo.mdb")
    Set QueryRS = New ADODB.Recordset
    QueryRS.CursorLocation = adUseClient
    Set QueryRS.ActiveConnection = CN
    Set XmlRS = New ADODB.Recordset
    XmlRS.ActiveConnection = "Provider=MSDAOSP;Data Source=MSXML2.DSOControl.3.0"
    Set UpdateRS = New ADODB.Recordset
    Set UpdateRS.ActiveConnection = CN
    UpdateRS.Properties("Append-Only Rowset").Value = True
    AppendFields = Array("flda", "fldb")
    RefreshGrid
End Sub

Private Sub Form_Resize()
    If WindowState <> vbMinimized Then
        FlexGrid.Move 0, 0, ScaleWidth, ScaleHeight
    End If
End Sub

Private Sub Form_Unload(Cancel As Integer)
    CN.Close
End Sub

Private Sub mnuImportXML_Click()
    XmlRS.Open "response.xml"
    Set recordsRS = XmlRS.Fields("record").Value
    UpdateRS.Open "Records", , , adLockOptimistic, adCmdTableDirect
    CN.BeginTrans
    With recordsRS
        Do Until .EOF
            UpdateRS.AddNew AppendFields, _
                            Array(.Fields(AppendFields(0)).Value, _
                                  .Fields(AppendFields(1)).Value)
            .MoveNext
        Loop
    End With
    CN.CommitTrans
    UpdateRS.Close
    Set recordsRS = Nothing
    XmlRS.Close
    RefreshGrid
End Sub

The key here is the Menu event handler mnuImportXML_Click (scroll down to the end) which appends the Text of the flda and fldb sub-elements of the repeated second-level XML element record into the Jet database table Records . 这里的关键是Menu事件处理程序mnuImportXML_Click (向下滚动到末尾),该事件处理程序将重复的第二级XML元素recordfldafldb子元素的Text附加到Jet数据库表Records

Note the use of: 注意以下用途:

UpdateRS.Properties("Append-Only Rowset").Value = True

That is done during initialization within Form_Load. 这是在Form_Load中初始化期间完成的。 It improves performance a bit. 它可以提高性能。

I'm not aware of any quicker way to accomplish this. 我不知道有什么更快的方法可以完成此操作。 Jet can't use an XML document as an external database. Jet不能将XML文档用作外部数据库。 It can only make use of database types that it has an IISAM for such as Text, HTML, Excel 8.0, dBase IV, and Paradox. 它只能使用具有IISAM的数据库类型,例如Text,HTML,Excel 8.0,dBase IV和Paradox。

Whether Microsoft was just lazy and left XML out of Jet 4.0 without thinking, the hierarchical nature of XML documents didn't leave them many options without extending Jet SQL syntax, or there is some syntax I haven't found... I just can't say. 微软是否只是懒惰而没有考虑过将XML从Jet 4.0中剔除,XML文档的层级性质在不扩展Jet SQL语法的情况下并没有为他们提供很多选择,或者我还没有找到某些语法...我可以不说

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM