【问题标题】:Execute MySQL stored procedure with parameters in Access frontend via VBA通过VBA在Access前端执行带有参数的MySQL存储过程
【发布时间】:2017-04-11 05:58:29
【问题描述】:

所以,数据库热点。

  • 我有一个包含存储过程的 MySQL 数据库。
  • 我有一个 Access 文档,它链接到 MySQL 数据库(我可以调查表)作为前端(包含表单和内容)
  • 我已经成功地创建了一个 ODBC 直通查询(我认为这就是它们的名称)来调用数据库中的一个存储过程。 Access 中的查询实际上只是 CALL myProcName;,当我使用 Set Result = CurrentDb.OpenRecordset("myProcName") 从 VBA 调用它时,它给出了我期望的结果

我想要达到的目标如下:

  • 在 MySQL 中有一个带有一个参数的存储过程 => 检查!
  • 该存储过程是否按预期工作 => 在 phpMyAdmin 中检查 => 检查!
  • 在 Access 中有一个保存的查询,该查询链接到这个参数存储过程,并给定了一个固定的参数值 => 检查! (CALL myProcName('myParameterValue'),我可以像执行非参数查询一样从 VBA 调用它)
  • 每次执行查询时都可以指定'myParameterValue' => 不检查

我需要以某种方式在已保存查询的 SQL 定义中指定一个参数占位符,并在 VBA 中设置该参数。对于我拥有的 VBA 部分,我认为我会觉得相当优雅:

Private Sub ParametricQuery()
  Dim QDef As QueryDef
  Set QDef = CurrentDb.QueryDefs("myProcName")
  QDef.Parameters(*insert parameter name here*) = parameter value
  Dim Result As Recordset
  Set Result = QDef.OpenRecordset

  Do While Not Result.EOF
    MsgBox Result.Fields(1) 'Display a field from the results
  Loop
End Sub

但是我将如何构建我的 SQL 定义?

PARAMETERS in_param TEXT;
CALL myProcName(in_param);

不起作用。如果我尝试

Set QDef = CurrentDb.QueryDefs("myProcName")
MsgBox QDef.Parameters.Count

我收到一个消息框,告诉我在我的查询定义中总共有 0 个参数,所以这不起作用。

我在网上发现很多人通过字符串操作在 VBA 中构建实际的 SQL。这让我不寒而栗,原因有很多(其中包括安全性、可维护性和优雅)。我坚信有更好的方法,希望能按照我上面勾勒的路线。唯一的问题是:怎么做?

【问题讨论】:

  • 你能在 MySQL 中发布CREATE PROCEDURE 行吗(不需要整个过程)?需要注意的是命名参数及其类型。
  • 嗯,我通过 myphpadmin 中相当不错的“创建过程”界面创建了该过程。它有一个方向为“IN”的参数(显然),类型为 VARCHAR,长度为 254(电子邮件地址的最大长度)。该程序执行简单的SELECT * FROM table WHERE field=param

标签: mysql vba ms-access stored-procedures parameter-passing


【解决方案1】:

考虑使用ADO 进行参数化查询来调用您的存储过程。目前,您正在使用DAO(Access 的默认数据库 API)来访问 pass-thru 查询(保存的 Access querydef)。但是,这种类型的查询在前端看不到任何东西,只有后端 RDMS,特别是 MySQL SQL 方言及其连接的数据库对象。因此,您不能将本地参数值绑定到它。而PARAMETERS 子句只是 Access SQL 方言的一部分,会导致 MySQL 语法失败。

MySQL存储过程

CREATE PROCEDURE `mystoredproc`(IN param VARCHAR(254))
BEGIN
   SELECT * FROM table WHERE field=param;
END

ADO参数化查询

Public Sub CallMySQLProc()    
    Dim conn As Object, cmd As Object, rst As Object
    Const adCmdStoredProc = 4, adParamInput = 1, adVarChar = 200

    Set conn = CreateObject("ADODB.Connection")
    Set rst = CreateObject("ADODB.Recordset")

    ' DSN-LESS CONNECTION
    conn.Open "Driver={MySQL ODBC 5.3 Unicode Driver};host=hostname;database=databasename;" _
                & "UID=username;PWD=****"

    ' CONFIGURE ADO COMMAND
    Set cmd = CreateObject("ADODB.Command")
    With cmd
        .ActiveConnection = conn
        .CommandText = "mystoredproc"
        .CommandType = adCmdStoredProc
        .CommandTimeout = 15
    End With

    ' APPEND NAMED PARAM
    cmd.Parameters.Append cmd.CreateParameter("param", adVarChar, _
                                              adParamInput, 254, "some.name@example.com")
    Set rst = cmd.Execute

    ' FREE RESOURCES
    rst.Close
    Set rst = Nothing
    Set cmd = Nothing
    Set conn = Nothing

End Sub

DAO动态直通查询

这里可以动态构建querydef的.SQL语句,但不会被参数化:

Private Sub ParametricQuery()
  Dim QDef As QueryDef
  Dim Result As Recordset

  Set QDef = CurrentDb.QueryDefs("PassThruQ")
  QDef.SQL = "CALL mystoredproc('some.name@example.com')"

  Set Result = QDef.OpenRecordset

  Do While Not Result.EOF
    Debug.Print Result.Fields(1)    'Print to immediate window a field from the results
  Loop

  Result.close
  Set Result = Nothing
  Set QDef = Nothing
End Sub

【讨论】:

  • 好的,所以不容易做到:)。有没有办法避免在代码中给出连接字符串? Acces 知道如何连接到数据库,它可以显示表。那么,为什么我需要再次指定密码并让所有人都清楚地看到呢?动态构建 SQL 有多安全?我看到了潜在的大量 SQL 注入,这是我试图避免的。做事(希望)正确和东西。但是到目前为止,谢谢!
  • 只需使用文件DSN,代码中不会显示任何凭据。您可以在 ODBC pass through 或 External Tools / ODBC 或 obdcad32.exe 的同一对话框中为您的 MySQL 数据库构建一个(存储的文本文件)。仅供参考 - ADO 可能是 VBA 中运行参数化查询的唯一方法!
  • 刚刚阅读了有关 DSN 的文章:我在窗口的控制面板中将我的数据库指定为 ODBC 数据源,Access 知道如何从那里连接到数据库,因此应该是系统 DSN。我有机会在 VBA 中使用它吗?信息就在那里……
  • 然后在连接字符串中指定它:conn.Open "DSN=DSN_Name"
  • 很抱歉这么晚才回复您,它有效!非常感谢!
猜你喜欢
  • 1970-01-01
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
  • 2016-10-19
相关资源
最近更新 更多