运行时错误3001'参数类型错误或超出可接受的范围......'

时间:2015-11-17 09:25:35

标签: sql-server excel vba excel-vba

我有一个Excel表,想要更新第12列Excel引用的SQL Server表记录的日期值(使用getdate函数)。

我的代码如下,但我看到了:

  

运行时错误3001参数类型错误或超出可接受的范围或彼此冲突。

在SQL表中,MODIFIEDDATE字段是datetime类型,MAINREF字段是整数类型。

Private Sub CommandButton2_Click()

Dim conn2 As New ADODB.Connection
Dim rst2 As New ADODB.Recordset
Dim j As Integer

conn2.ConnectionString = "Provider=SQLOLEDB.1;Password=abc;Persist Security Info=True;User ID=sa;Initial Catalog=logodb;Data Source=A3650;Use Procedure for Prepare=1;Auto"
conn2.Open

For j = 0 To 1900
    If Sayfa1.Cells(j + 4, 12) = "" Then
        Sayfa1.Cells(j + 4, 13) = "empty"
    Else
        rst2.Open "UPDATE T_015 SET MODIFIEDDATE=GETDATE() WHERE MAINREF='" & Sayfa1.Cells(j + 4, 12) & "'", conn, 1, 3
        rst2.Close
    End If
Next j

End Sub

我尝试更改SQL查询,如(CInt(cell.value))

rst2.Open "UPDATE T_015 SET MODIFIEDDATE=GETDATE() WHERE MAINREF='" & CInt(Sayfa1.Cells(j + 4, 12)) & "'", conn, 1, 3

但是,它没有用。

2 个答案:

答案 0 :(得分:0)

ADODB.Recordset对象不应用于UPDATE查询。直接从ADODB.Connection

执行SQL语句
Dim conn2 As New ADODB.Connection

conn2.ConnectionString = "Provider=SQLNCLI11;Server=MYSERVER;Database=TMP;UID=sa;password=abc;"
conn2.Open

conn2.Execute "UPDATE T_015 SET MODIFIEDDATE=GETDATE() WHERE MAINREF=1"

答案 1 :(得分:0)

有两种方法可以满足您的要求,似乎您正在混合这两种方式。

一种方法是一次更新一个记录,为此,您可以使用Connection对象,或者更优选地使用Command对象。我说最好是因为参数化命令是一种更健壮的SQL执行方式。如果您打算使用SQL,那么您可能应该阅读它。你这样做的方式如下:

Public Sub ParameterisedProcedure()
    Dim conn As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim prm As ADODB.Parameter
    Dim v As Variant
    Dim j As Integer

    'Read the sheet data
    v = Sayfa1.Range("L4", "M1904").Value2

    'Open the database connection
    Set conn = New ADODB.Connection
    conn.ConnectionString = "Provider=SQLOLEDB.1;" & _
                              "Password=abc;" & _
                              "Persist Security Info=True;" & _
                              "User ID=sa;" & _
                              "Initial Catalog=logodb;" & _
                              "Data Source=A3650;" & _
                              "Use Procedure for Prepare=1;" & _
                              "Auto"
    conn.Open

    'Loop through the values to update records
    For j = 1 To UBound(v, 1)
        If IsEmpty(v(j, 1)) Then
            v(j, 2) = "empty"
        Else
            'Create the parameterised command
            Set cmd = New ADODB.Command
            cmd.ActiveConnection = conn
            cmd.CommandType = adCmdText
            cmd.CommandText = "UPDATE T_015 " & _
                              "SET MODIFIEDDATE=? " & _
                              "WHERE MAINREF=?"
            prm = cmd.CreateParameter(Type:=adDate, Value:=Now)
            cmd.Parameters.Append prm
            prm = cmd.CreateParameter(Type:=adInteger, Value:=v(j, 1))
            cmd.Parameters.Append prm
            cmd.Execute
        End If
    Next

    'Write the updated values
    Sayfa1.Range("L4", "M1904").Value = v

    'Close the database
    Set prm = Nothing
    Set cmd = Nothing
    conn.Close

End Sub

另一种方法是使用Transactions,你确实会使用Recordset(就像你已经完成的那样)。在这种情况下,我建议这是更好的方法,因为一次执行一个命令(如上面的代码)是非常慢的。更快捷的方法是在一个事务中提交所有更新。与参数化命令一样,输入SQL命令文本的恶意字符串也是安全的。代码如下所示:

Public Sub TransactionProcedure()
    Dim conn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim cmdText As String
    Dim v As Variant
    Dim j As Integer

    'Read the sheet data
    v = Sayfa1.Range("L4", "M1904").Value2

    'Open the database connection
    Set conn = New ADODB.Connection
    conn.ConnectionString = "Provider=SQLOLEDB.1;" & _
                              "Password=abc;" & _
                              "Persist Security Info=True;" & _
                              "User ID=sa;" & _
                              "Initial Catalog=logodb;" & _
                              "Data Source=A3650;" & _
                              "Use Procedure for Prepare=1;" & _
                              "Auto"
    conn.Open

    'Retrieve the data
    Set rs = New ADODB.Recordset
    cmdText = "SELECT * FROM  T_015"
    rs.Open cmdText, conn, adOpenStatic, adLockReadOnly, adCmdText

    'Loop through the values to update the recordset
    On Error GoTo EH
    conn.BeginTrans
    For j = 1 To UBound(v, 1)
        If IsEmpty(v(j, 1)) Then
            v(j, 2) = "empty"
        Else
            'Find and update the record
            rs.Find "MAINREF=" & CStr(v(j, 1))
            If Not rs.EOF Then
                rs!ModifiedDate = Now
                rs.Update
            End If
        End If
    Next
    conn.CommitTrans

    'Write the updated values
    Sayfa1.Range("L4", "M1904").Value = v

    'Close the database
    rs.Close
    conn.Close
    Exit Sub

EH:
    conn.RollbackTrans
    Sayfa1.Range("L4", "M1904").Value = v
    rs.Close
    conn.Close
    MsgBox Err.Description
End Sub