【问题标题】:Runtime error 3001 'Arguments are of the wrong type or out of acceptable range…' INSERT INTO MySQL Database运行时错误 3001 '参数类型错误或超出可接受范围...' INSERT INTO MySQL 数据库
【发布时间】:2020-01-17 10:01:43
【问题描述】:

我知道有很多相同类型的问题,但没有人帮助我,我真的被困住了。 所以我正在尝试使用 VBA 从 Excel 表中发送数据,但我总是收到相同的错误:'运行时错误 3001'参数类型错误或超出可接受范围' 问题是我不明白我的错误来自哪里?是来自我的 SQL 查询还是来自 Visual Basic 代码? 我的代码在 3 sub

Dim oConn As ADODB.Connection

第二个

Private Sub ConnectDB()
    Set oConn = New ADODB.Connection
    Dim str As String

    str = "DRIVER={MySQL ODBC 5.1 Driver};" & _
          "SERVER=XXX.XXX.XXX.XXX" & ";" & _
          "PORT=3306" & ";" & _
          "DATABASE=myDB" & ";" & _
          "USER=User" & ";" & _
          "PASSWORD=pwd" & ";" & _
          "Option=3"

    ''' error '''
    oConn.Open str
End Sub

最后一个

Sub InsertData()    
    Dim Rs As ADODB.Recordset

    Dim Requete As String

    Set Rs = New ADODB.Recordset
    Call ConnectDB
    With Sheets("Feuil5")
        Requete = "INSERT INTO Position (Emplacement,Etage,Colonne,Taille) VALUES ('1','1','1','1');"
        Rs.Open Requete, oConnect, adOpenDynamic, adLockOptimistic
    End With
    Debug.Print Requete
    oConnect.Close
    Set Rs = Nothing
End Sub

有人能找到我的错误并帮助在 vba 中实现和简单的 sql 查询吗?

【问题讨论】:

  • 您正在将字符串插入Position 表中。列是字符串值吗?
  • 等等,为什么在另一个范围内声明了oConnDim 用于局部变量,因此 ConnectDB 分配给未声明的变量。在每个模块的顶部指定Option Explicit,然后声明局部变量,直到代码再次编译(调试~> 编译 VBAProject)。 oConn.Open str 的错误是什么(注意,Str 是一个糟糕的名字,它实际上隐藏了 VBA 标准库中现有的全局范围函数)。
  • 插入可能失败,因为您将 5 个值插入 4 列。
  • 所以是的,我所有的列都是 Varchar 数据类型,它是一个变量 String 对吗?我在Private Sub ConnectDB() 之后移动了Dim oConn As ADODB.Connection。我尝试使用 Option Explicit,但每次都会出错。我在oConn.Open str 上没有任何错误,我现在将 str 更改为 S
  • 您在使用 Option Explicit 时遇到错误,因为您使用的变量未在任何地方声明,或者无法访问:这完全符合预期 - Option Explicit 通过拒绝帮助强制执行正确性编译使用未声明变量的代码。解决方案是声明你的变量,而不是删除Option Explicit

标签: mysql sql excel vba sql-insert


【解决方案1】:

ConnectDB 的工作是创建数据库连接。不要分配给在另一个范围内声明的某个 oConn 对象(可能已经连接并打开),而是将其设为 Function

Private Function ConnectDB() As ADODB.Connection
    Dim conn As ADODB.Connection
    Set conn = New ADODB.Connection

    Const connString As String = _
      "DRIVER={MySQL ODBC 5.1 Driver};" & _
      "SERVER=XXX.XXX.XXX.XXX;" & _
      "PORT=3306l" & _
      "DATABASE=myDB;" & _
      "USER=User;" & _
      "PASSWORD=pwd;" & _
      "Option=3"

    On Error GoTo CleanFail
    conn.Open connString
    Set ConnectDB = conn
    Exit Function
CleanFail:
    Debug.Print "Error opening database connection:"
    Debug.Print Err.Number, Err.Description
    Debug.Print "ConnectDB is returning Nothing."
    Set ConnectDB = Nothing
End Function

现在您有一个函数,该函数要么连接并返回一个实时的ADODB.Connection,要么不连接并返回Nothing,而且所有涉及的值的范围都没有超出它们所需的范围。

所以InsertData 现在可以使用它了。现在,我们根本不需要Recordset - 我们不关心任何记录,我们只想运行INSERT 查询;这可能会针对连接本身运行 - 请注意,VALUES 的数量必须与 INSERT INTO 子句中指定的列数相匹配......并且由于一组硬编码的值不是很有用,你会希望这些值正确参数化(不要将工作表单元格值连接到您的 SQL 语句中 - meet Little Bobby Tables):

Public Sub InsertData(ByVal emplacement As String, ByVal etage As String, ByVal colonne As String, ByVal taille As String)
    Dim conn As ADODB.Connection
    Set conn = ConnectDB
    If conn Is Nothing Then
        ' couldn't connect to database; review Debug output, fix connection string.
        MsgBox "Could not connect to database.", vbExclamation
        Exit Sub
    End If

    Const sql As String = _
        "INSERT INTO Position (Emplacement, Etage, Colonne, Taille) " &
        "VALUES(?, ?, ?, ?) "

    Dim cmd As ADODB.Command
    Set cmd = New ADODB.Command

    Set cmd.ActiveConnection = conn
    cmd.CommandType = adCmdText
    cmd.CommandText = sql

    'TODO: verify parameter types & sizes.
    'NOTE: parameters must be added in the order they are specified in the SQL.
    cmd.Parameters.Append cmd.CreateParameter(Type:=adVarWChar, Size:=200, Value:=emplacement)
    cmd.Parameters.Append cmd.CreateParameter(Type:=adVarWChar, Size:=200, Value:=etage)
    cmd.Parameters.Append cmd.CreateParameter(Type:=adVarWChar, Size:=200, Value:=colonne)
    cmd.Parameters.Append cmd.CreateParameter(Type:=adVarWChar, Size:=200, Value:=taille)

    On Error GoTo CleanFail
    cmd.Execute '<~ when you DO need a recordset, this gets you your recordset.
CleanExit:
    conn.Close
    Exit Sub
CleanFail:
    Debug.Print "Error executing command: " & sql
    Debug.Print Err.Number, Err.Description
    Resume CleanExit
End Sub

【讨论】:

  • 感谢您的回答。我真的很抱歉,但我从 vba 开始,我不明白我应该在哪里添加 Cell(1,2) 例如。我应该在Value:= 之后添加这个而不是 emplacement 吗?
  • @LukaAUDE 该程序采用 4 个参数;当您调用该过程时,您提供了值 - 它们可能来自工作表单元格、硬编码的测试输入或任何东西......该过程不需要知道。 InsertData Sheet1.Cells(1, 2).Value, Sheet1.Cells(1, 3).Value, Sheet1.Vells(1, 4).Value, Sheet1.Cells(1, 5).ValueInsertData "test", "test", "test", "test" 一样有效
【解决方案2】:

好吧,为了解决这个问题,我将所有内容都添加到一个子中,这里是我所知道的:

Private Sub ConnectDB()
Dim oConn As ADODB.Connection
Set oConn = New ADODB.Connection
Dim Rs As ADODB.Recordset
Dim Requete As String
Set Rs = New ADODB.Recordset
Dim S As String

S = "DRIVER={MySQL ODBC 5.1 Driver};" & _
      "SERVER=XXX.XXX.XXX.XXX" & ";" & _
      "PORT=3306" & ";" & _
      "DATABASE=x" & ";" & _
      "USER=x" & ";" & _
      "PASSWORD=x" & ";" & _
      "Option=3"

''' error '''
oConn.Open S

Requete = "INSERT INTO Position(Emplacement,Etage,Colonne,Taille) VALUES('test','test','test','test');"

    Rs.Open Requete, oConn, adOpenDynamic, adLockOptimistic

    Debug.Print Requete
    oConn.Close
    Set Rs = Nothing

End Sub

它解决了我最初的问题,但现在我遇到了另一个问题(执行错误'-2147217887 (80040e21)': 该驱动程序不支持请求的属性)但无论如何感谢您的帮助,我现在将尝试找到我的另一个错误。 祝你有美好的一天

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 1970-01-01
    相关资源
    最近更新 更多