当只有一些字段是常见的时,如何合并两个数据库表?

时间:2013-09-13 21:07:30

标签: sql ms-access merge

在MS Access中,我有两个表(A和B),任务是将B插入A.但是,有一些特殊条件:

  • 所有字段均为文字类型。
  • A和B有一些共同的领域。
  • 两者都保证存在相同的关键字段,并且其值始终不同。
  • A有一些B没有的字段。插入的记录应该将这些字段留空。
  • B有一些A没有的字段。必须在A中创建这些字段,并且A中的现有记录应将它们留空。
  • 有很多这样的情况,因此查询不应该明确包含字段名称,因为为每个案例个性化查询会很繁琐。但是,关键字段的名称始终相同。
  • 创建新表C而不是直接替换A是可以接受的。

示例:

Table A:
key  a       b       c
--- ------- ------- -------
k0  hello   dear    world
k1  bye     cruel   world

Table B:
key  a       d       e
--- ------- ------- -------
k2  welcome john    doe
k3  turulu  ann     harp

Table C (the new A):
key  a       b       c       d       e
--- ------- ------- ------- ------- -------
k0  hello   dear    world
k1  bye     cruel   world
k2  welcome                 john    doe
k3  turulu                  ann     harp

2 个答案:

答案 0 :(得分:1)

创建一个访问模块并使用以下代码。用表和目标名称替换test子中的值

Option Compare Database
Option Explicit

Function SplatTablesSql(pT1 As String, pT2 As String, pDest As String)
    Dim lDb As Database
    Dim lTd1 As TableDef, lTd2 As TableDef
    Dim lField As Field, lF2 As Field
    Dim lS1 As String, lS2 As String, lSep As String

    SplatTablesSql = "Select "
    lS1 = "Select "
    lS2 = "Select "

    Set lDb = CurrentDb
    Set lTd1 = lDb.TableDefs(pT1)
    Set lTd2 = lDb.TableDefs(pT2)

    For Each lField In lTd1.Fields
        SplatTablesSql = SplatTablesSql & lSep & "x.[" & lField.Name & "]"
        lS1 = lS1 & lSep & "a.[" & lField.Name & "]"
        Set lF2 = Nothing
        On Error Resume Next
        Set lF2 = lTd2.Fields(lField.Name)
        On Error GoTo 0
        If lF2 Is Nothing Then
            lS2 = lS2 & lSep & "Null"
        Else
            lS2 = lS2 & lSep & "b.[" & lField.Name & "]"
        End If
        lSep = ", "
    Next

    For Each lField In lTd2.Fields
        Set lF2 = Nothing
        On Error Resume Next
        Set lF2 = lTd1.Fields(lField.Name)
        On Error GoTo 0
        If lF2 Is Nothing Then
            SplatTablesSql = SplatTablesSql & lSep & "x.[" & lField.Name & "]"
            lS1 = lS1 & lSep & "Null as [" & lField.Name & "]"
            lS2 = lS2 & lSep & "b.[" & lField.Name & "]"
        End If
        lSep = ", "
    Next

    SplatTablesSql = SplatTablesSql & " Into [" & pDest & "] From ( " & lS1 & " From [" & pT1 & "] a Union All " & lS2 & " From [" & pT2 & "] b ) x"
End Function

Sub Test()

    CurrentDb.Execute SplatTablesSql("a", "b", "c")

End Sub

答案 1 :(得分:1)

我能想到解决这个问题的最简单方法是使用VBA创建查询定义。

我将假设有一个名为key的列,这两个表都是通用的。

我发现here你可以使用集合来制作类似字典的结构。我将使用它来构建字段列表。

所以,我们走了:

public function contains(col as Collection, key as variant) as boolean
    dim obj as variant
    on error goto err
        contains = True
        obj = col(key)
        exit function
    err:
        contains = false
end function

public sub create_this_query(tbl1 as String, tbl2 as String, keyField as String)
    ' tbl1 and tbl2 are the names of the tables you'll use
    dim db as DAO.database, rs1 as DAO.recordset, rs2 as DAO.recordset
    dim columns as Collection
    dim strSQL as String
    dim i as integer
    dim obj as variant, colName as String

    set db = currentdb()
    set tbl1 = db.openrecordset(tbl1, dbopendynaset, dbreadonly)
    set tbl2 = db.openrecordset(tbl2, dbopendynaset, dbreadonly)
    set columns = new Collection

    ' Let's create the field list (ommiting the keyField)
    for i = 1 to tbl1.fields.count
        if not contains(columns, tbl1.fields(i).Name) _
           and tbl1.fields(i).Name <> keyField then
            columns.add tbl1.fields(i).Name, tbl1.fields(i).Name
        end if
    next i
    for i = 1 to tbl2.fields.count
        if not contains(columns, tbl2.fields(i).Name) _
           and tbl2.fields(i).Name <> keyField then
            columns.add tbl1.fields(i).Name, 1 ' The value is just a placeholder
        end if
    next i
    ' Now let's build the SQL instruction
    strSQL = "select [a].[" & keyField & "]"
    for colName in columns
        strSQL = strSQL & ", [" & colName & "]"
    next obj
    strSQL = strSQL & " " & _
             "from " & _
             "    (" & _
             "        select [" & keyField & "] from [" & tbl1 & "] " & _
             "        union " & _
             "        select [" & keyField & "] from [" & tbl2 & "] " & _
             "    ) as a " & _
             "left join [" & tbl1 & "] as t1 " & _
             "    on a.[" & keyField & "] = t1.[" & keyField & "] " & _
             "left join [" & tbl2 & "] as t2 " & _
             "    on a.[" & keyField & "] = t2.[" & keyField & "] "
   ' Finally, let's create the query object
   db.createQueryDef("myNewQuery", strSQL)
end sub

希望这有帮助