MS Access 链接到 SQL 服务器视图

Posted

技术标签:

【中文标题】MS Access 链接到 SQL 服务器视图【英文标题】:MS Access linked to SQL server views 【发布时间】:2009-06-24 03:47:41 【问题描述】:

我们正在升级使用 SQL Server 作为其数据存储的访问数据库存在问题。

这个特定的数据库链接到 2 个 sql 数据库,所以我想简化一下,我们在主数据库中有一个视图,它链接到辅助数据库中的每个表。这样一来,访问只需要直接与一个 SQL 数据库对话。

当我们链接对数据库视图的访问时,我们选择哪些字段是主键,因此视图不是只读的。我们有标准代码,当数据库打开以获取任何更改时刷新所有链接,并且链接视图因为主键信息丢失而变为只读。

有没有办法在保留主键信息的同时刷新视图链接?

约翰

【问题讨论】:

如何刷新链接?另外 - 数据库结构(在 sql server 中)是否经常更改以获取该信息? 【参考方案1】:

我在下面包含了我的整个 ODBC 重新连接功能。这个函数的前提是我有一个名为 rtblODBC 的表,它存储了我重新连接所需的所有信息。如果你实现了这个功能,你就不必担心连接到多个 SQL 数据库,因为每个要重新连接的表都有自己的连接字符串,这可以顺利处理。

当您接近尾声时,您会看到我使用 DAO 通过 db.Execute "CREATE INDEX " & sPrimaryKeyName & " ON " & sLocalTableName & "(" & sPrimaryKeyField & ")WITH PRIMARY;" 重新创建主键

如果您有任何问题,请提出。

Public Function fnReconnectODBC( _
    Optional bForceReconnect As Boolean _
    ) As Boolean
    ' Comments  :
    ' Parameters: bForceReconnect -
    ' Returns   : Boolean -
    ' Modified  :
    ' --------------------------------------------------'

    On Error GoTo Err_fnReconnectODBC

    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim tdf As DAO.TableDef
    Dim sPrimaryKeyName As String
    Dim sPrimaryKeyField As String
    Dim sLocalTableName As String
    Dim strConnect As String
    Dim varRet As Variant

    Dim con As ADODB.Connection
    Dim rst As ADODB.Recordset
    Dim sSQL As String

    If IsMissing(bForceReconnect) Then

        bForceReconnect = False

    End If

    sSQL = "SELECT rtblODBC.LocalTableName, MSysObjects.Name, MSysObjects.ForeignName, rtblODBC.SourceTableName, MSysObjects.Connect, rtblODBC.ConnectString " _
         & "FROM MSysObjects RIGHT JOIN rtblODBC ON MSysObjects.Name = rtblODBC.LocalTableName " _
         & "WHERE (((rtblODBC.ConnectString)<>'ODBC;' & [Connect]));"

    Set con = Access.CurrentProject.Connection
    Set rst = New ADODB.Recordset

    rst.Open sSQL, con, adOpenDynamic, adLockOptimistic

        'Test the recordset to see if any tables in rtblODBC (needed tables) are missing from the MSysObjects (actual tables)
        If rst.BOF And rst.EOF And bForceReconnect = False Then

            'No missing tables identified
            fnReconnectODBC = True

        Else

            'Table returned information, we don't have a perfect match, time to relink
            Set db = CurrentDb
            Set rs = db.OpenRecordset("rtblODBC", dbOpenSnapshot)

                'For each table definition in the database collection of tables
                For Each tdf In db.TableDefs

                    'Set strConnect variable to table connection string
                    strConnect = tdf.Connect

                    If Len(strConnect) > 0 And Left(tdf.Name, 1) <> "~" Then

                        If Left(strConnect, 4) = "ODBC" Then

                            'If there is a connection string, and it's not a temp table, and it IS an odbc table
                            'Delete the table
                            DoCmd.DeleteObject acTable, tdf.Name

                        End If

                    End If

                Next

                'Relink tables from rtblODBC
                With rs

                    .MoveFirst

                    Do While Not .EOF

                        Set tdf = db.CreateTableDef(!localtablename, dbAttachSavePWD, !SourceTableName, !ConnectString)

                        varRet = SysCmd(acSysCmdSetStatus, "Relinking '" & !SourceTableName & "'")

                        db.TableDefs.Append tdf
                        db.TableDefs.Refresh

                        If Len(!PrimaryKeyName & "") > 0 And Len(!PrimaryKeyField & "") > 0 Then

                            sPrimaryKeyName = !PrimaryKeyName
                            sPrimaryKeyField = !PrimaryKeyField
                            sLocalTableName = !localtablename

                            db.Execute "CREATE INDEX " & sPrimaryKeyName & " ON " & sLocalTableName & "(" & sPrimaryKeyField & ")WITH PRIMARY;"

                        End If

                        db.TableDefs.Refresh

                        .MoveNext

                    Loop

                End With

            subTurnOffSubDataSheets

            fnReconnectODBC = True

        End If

    rst.Close
    Set rst = Nothing

    con.Close
    Set con = Nothing


Exit_fnReconnectODBC:

    Set tdf = Nothing
    Set rs = Nothing
    Set db = Nothing

    varRet = SysCmd(acSysCmdClearStatus)

    Exit Function

Err_fnReconnectODBC:

    fnReconnectODBC = False

    sPrompt = "Press OK to continue."
    vbMsg = MsgBox(sPrompt, vbOKOnly, "Error Reconnecting")
    If vbMsg = vbOK Then

        Resume Exit_fnReconnectODBC

    End If

End Function

【讨论】:

David,不幸的是,当代码尝试附加 tabledef 时,我们收到错误 3264。约翰 David,稍作修改,我们没有删除并重新创建tabledef,而是使用DAO refreshlink,然后创建了索引,效果很好。感谢您的帮助【参考方案2】:

大量将访问表重新链接到 SQL Server 的 DSN 较少的代码通常会先删除链接,然后再重新创建链接。然后代码设置连接字符串。因此,正是删除导致您丢失了主键曾经/现在的内容。

我实际上建议您修改重新链接代码,以免删除表链接。

尝试类似:

For Each tdfCurrent In dbCurrent.TableDefs
   If Len(tdfCurrent.Connect) > 0 Then
      If Left$(tdfCurrent.Connect, 5) = "ODBC;" Then
         strCon = "ODBC;DRIVER=sql server;" & _
           "SERVER=" & ServerName & ";" & _
           "DATABASE=" & DatabaseName & ";" & _
           "UID=" & UserID & ";" & _
           "PWD=" & USERpw & ";" & _
           "APP=Microsoft Office 2003;" & _
           "WSID=" & WSID & ";"
        End If
     End If
     tdfCurrent.Connect = strCon
     tdfCurrent.RefreshLink
  End If
Next tdfCurrent

【讨论】:

【参考方案3】:

这对我来说效果好一点(注意移动端 if's):

Dim dbCurrent As Database
Set dbCurrent = CurrentDb()

StatusList.SetFocus
StatusList.AddItem ("starting... ")
I = DoEvents()
Dim tdfCurrent As DAO.TableDef
For Each tdfCurrent In dbCurrent.TableDefs
   If Len(tdfCurrent.Connect) > 0 Then
      If Left$(tdfCurrent.Connect, 5) = "ODBC;" Then
         strCon = "ODBC;DRIVER=sql server;" & _
           "SERVER=" & ServerName & ";" & _
           "DATABASE=" & DatabaseName & ";" & _
           "UID=" & UserID & ";" & _
           "PWD=" & USERpw & ";" & _
           "APP=Microsoft Office 2003;" & _
           "WSID=" & WSID & ";"

           StatusList.AddItem ("fixing " & tdfCurrent.Name)
        tdfCurrent.Connect = strCon
        tdfCurrent.RefreshLink
     End If
  End If
  I = DoEvents()
Next tdfCurrent

  StatusList.AddItem ("----Done.")

ODBC 检查是正确的,即使 "ODBC;"部分未显示在 MSysObjects 视图中。

【讨论】:

以上是关于MS Access 链接到 SQL 服务器视图的主要内容,如果未能解决你的问题,请参考以下文章

迁移到新的 SQL Server 后,在 MS Access 中更新链接表的最佳方法是啥?

MS Access:在设计指南视图中创建链接表不显示要链接的表?

MS-Access 将 SQL 服务器 datetime2 字段视为 TEXT

我可以将 MS Access 应用程序链接到 Linux 服务器上的 Postgresql 吗?可以/我应该使用 ODBC 吗?

将查询从 SQL 服务器复制到 MS Access

强制 MS Access 将完整查询发送到 SQL 服务器