如何在VBA中用ADO连接远程的access数据库

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在VBA中用ADO连接远程的access数据库相关的知识,希望对你有一定的参考价值。

参考技术A 远程连接access数据库的几个方法:
1.建立VPN(Virtual Private Network),然后把服务器中mdb文件所在的 Folder 共享即可。连接方法如下:
   “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\\服务器名\\文件夹 \\mydata.mdb;Jet
OLEDB:Database Password=datapass;Persist Security Info=False”
2.把数据库放在Web 服务器上,使ADO或RDO通过RDS(Remote Data Service) 及IIS来实现:
如果服务器设置了ODBC DSN的话,连接方法如下:
"Provider=MS Remote;Remote Server=http://服务器名;Remote Provider=MSDASQL;DSN=AdvWorks;Uid=dataUserName;Pwd=dataPassWord"
如果设置的是OLE DB Provider 的话,连接方法如下:
  "Provider=MS Remote;Remote Server=http://服务器名;Remote
Provider=Microsoft.Jet.OLEDB.4.0; Data Source=数据库文件路径,"+ "admin,"+"" (数据库用户名为:admin;密码为空)
3.编写服务器程序,通过TCP/IP,传递Recordset。
4.使用第三方控件,如:ADO Anywhere或UDAParts RDB等。
5.使用XMLHTTP

应用举例
OledbConnection myconn = null;
myconn = new OledbConnection("192.168.1.155", "DSN=mydata;DRIVER=Microsoft Access Driver (*.mdb);UID=test;PWD=test;"); //其中服务器IP是 192.168.1.155 ;数据库名是 mydata ;数据库用户名这密码都是test myconn.Open();

在 VBA 中使用 KDB+/qodbc.dll 的 ADO

【中文标题】在 VBA 中使用 KDB+/qodbc.dll 的 ADO【英文标题】:ADO with KDB+/qodbc.dll in VBA 【发布时间】:2014-08-26 13:37:35 【问题描述】:

我有一个基于 Excel 的应用程序,它依赖于我使用 ADO(Microsoft ActiveX 数据对象 6.1 库)连接到的几个不同的数据库。数据库驻留在区域服务器上,建立初始连接会产生开销,因此我将连接缓存在 Scripting.Dictionary 对象中以供重用。

Private moConnCacheDict As Scripting.Dictionary

当我使用 kdb+ qodbc.dll 数据库驱动程序时,我得到了意外的行为。我可以按预期连接和重用多个数据源(Oracle、Sybase、Access)和一个 KDB 数据库实例。但是,如果我创建第二个 KDB 数据库连接并对新数据集执行查询,尽管查询是合法的,但不会返回任何数据。

Recordset.BOF = TRUE and Recordset.EOF = TRUE 

它似乎执行得很好,并且这些字段是可见的。与以前的区域服务器的连接似乎仍然存在,我可以成功检索驻留在原始服务器上的数据,尽管如果我看一下,

Recordset.ActiveCommand.ActiveConnection.Properties.Item("Extended Properties")

,是新的连接字符串。

KDB+ 连接字符串使用以下语法:

DRIVER=kdb+;DBQ=XXXXX;UID=XXXXX;PWD=XXXXX;

我已经包含了用作示例的核心 VBA 函数:

Private Function ExecuteQuery(sDBName As String, ByRef oRst As ADODB.Recordset, Optional bDeleteConnection As Boolean) As Boolean
Dim oDBConn As ADODB.Connection
Dim sSql As String

'delete connection
If bDeleteConnection Then Call DropConnection(sDBName)

'get cached or new connection
Call GetConnection(sDBName, oDBConn)

Select Case sDBName
Case "MAIN_US"
    sSql = mSQL_MAIN
Case "MD_ASIA"
    sSql = mSQL_MDASIA
End Select

Set oRst = New Recordset
oRst.Open sSql, oDBConn, adOpenKeyset, adLockPessimistic

If Not oDBConn.State = adStateOpen Then Err.Raise vbObjectError + 1024, "ExecuteQuery", sDBName & ": Recordset Closed. Unable to execute query ->" & sSql

ExecuteQuery = True

End Function

Private Function GetConnection(sDBName As String, ByRef oDBConn As ADODB.Connection) As Boolean

If moConnCacheDict Is Nothing Then Set moConnCacheDict = New Dictionary

If moConnCacheDict.Exists(sDBName) Then
'get existing connection
Set oDBConn = moConnCacheDict.Item(sDBName)
Else
'create connection
Set oDBConn = New Connection

With oDBConn
    .Mode = adModeRead
    Select Case sDBName
    Case "MAIN_US"
        .Mode = adModeReadWrite
        .ConnectionString = mCONN_MAIN
    Case "MD_ASIA"
        .Mode = adModeRead
        .ConnectionString = mCONN_MDASIA
    End Select

    .CursorLocation = adUseServer
    .Open
End With

moConnCacheDict.Add sDBName, oDBConn

End If

GetConnection = True

End Function

Private Function DropConnection(Optional sDBName As String) As Boolean
Dim oDBConn As ADODB.Connection
Dim i As Integer

    'delete object directly from cache
    If Not moConnCacheDict Is Nothing Then
        If sDBName = vbNullString Then
                'close all connections
                For i = 0 To moConnCacheDict.Count - 1
                    If Not IsEmpty(moConnCacheDict.Items(i)) Then
                        Set oDBConn = moConnCacheDict.Items(i)
                        If Not oDBConn Is Nothing Then
                            If oDBConn.State = adStateOpen Then oDBConn.Close
                            Set oDBConn = Nothing
                            Debug.Print Now, "Dropping Database Connection - " & moConnCacheDict.Keys(i)
                        End If
                    End If
                Next i
                Set moConnCacheDict = Nothing
            Else
            If moConnCacheDict.Exists(sDBName) Then
                If Not IsEmpty(moConnCacheDict.Item(sDBName)) Then
                    Set oDBConn = moConnCacheDict.Item(sDBName)
                    If Not oDBConn Is Nothing Then
                        If oDBConn.State = adStateOpen Then oDBConn.Close
                        Set oDBConn = Nothing
                        Debug.Print Now, "Dropping Database Connection - " & "Dropping Database Connection - " & sDBName
                    End If
                End If
                moConnCacheDict.Remove (sDBName)
            End If
        End If
    End If

DropConnection = True

End Function

(请注意,ADO.Recordset 始终被调用者关闭并设置为空)。

解决此问题的唯一方法是关闭所有数据库连接(无论提供者如何),然后重新连接到所需的区域服务器。这是非常低效的,因为我必须重新打开所有现有的连接。另请注意,仅在当前工作簿中执行此操作是不够的。 这必须在应用程序级别完成。如果与任何数据库的任何 ADO 连接仍然打开,我可以创建一个新的 KDB+ ADO 连接,但它仍将指向前一个实例

我查看了KDB+连接对象的错误属性,有两个错误:

    多步 OLE DB 操作产生错误。检查每个 OLE DB 状态值(如果可用)。没有完成任何工作。 提供者不支持该属性。

这似乎记录在 http://support.microsoft.com/kb/269495 中,但我无法在注册表中找到任何 CLSID,因此无法尝试建议的更改。

如果我打开 ODBC 日志记录,我会看到以下消息:

EXCEL                   8dc-22d0    EXIT  SQLGetInfoW  with return code -1 (SQL_ERROR)
    HDBC                0x02131EA8
    UWORD                      151 <SQL_KEYSET_CURSOR_ATTRIBUTES2>
    PTR                 0x003C4FB0
    SWORD                        4 
    SWORD *             0x00000000

    DIAG [S1096] [Microsoft][ODBC Driver Manager] Information type out of range (0) 

这是否会导致错误?

一如既往,我们将不胜感激任何帮助和建议。

【问题讨论】:

对我来说听起来像是 KDB+ OLE DB 驱动程序中的一个错误。我的建议是创建一个 minimal、可重现的示例(只需打开两个 KDB+ 连接并显示第二个连接不符合预期)并将其作为错误发送给 KDB+ 开发人员报告。 【参考方案1】:

您看到的是驱动程序中的错误,您应该寻找更新的驱动程序。

如果我自己没有运行和测试代码,我真的不应该给出完整的答案(而不是评论),但我建议您枚举连接对象的属性集合并查找连接池。

将连接池设置为 0(或设置为 false,这取决于您通过查看属性值的 vartype 可以猜到什么)是一种很有前途的解决方法。您的另一个选择是使用只进的记录集:这可能有效也可能无效,但值得一试。

注意:几年前有一个开源项目来编写适当的 OLEDB 驱动器,但似乎已经淡出人们的视线。

【讨论】:

连接对象上没有称为连接池的属性,转发只做任何事情。还是谢谢。 枚举Connection对象的属性集合: For i = 0 to oConn.Properties.Count-1 Debug.Print i & vbtab & oConn.Properties(i).Name & " = " & oConn .Properties(i).value next i

以上是关于如何在VBA中用ADO连接远程的access数据库的主要内容,如果未能解决你的问题,请参考以下文章

在 VBA 中打开与 Excel 电子表格的 ADO 连接

VBA Excel里 用ADO访问ACCESS数据库的问题

奇怪的情况,使用 ADO 在 Excel VBA 中定义连接到 Access .accdb 数据库的文件路径,但是它告诉我找不到 .mdb 文件

在access中用vba如何把SQL语句查询到的一个值赋给变量?

ADO 无法识别旧式 SQL 连接。不知道如何在此特定查询中使用新式语法

ACCESS中用VBA如何导入当前目录内的指定EXCEL