如何使用 VBA 执行插入/更新记录的存储过程?

Posted

技术标签:

【中文标题】如何使用 VBA 执行插入/更新记录的存储过程?【英文标题】:How to execute stored procedure which insert/update records using VBA? 【发布时间】:2021-12-03 01:06:58 【问题描述】:

我创建了许多使用存储过程的电子表格。我有一个自定义 VBA 代码,当我尝试从 SQL 获取数据时它工作正常。但是,今天我想执行参数化的存储过程,在数据库表上插入和更新数据。当我运行宏时没有出现错误,但是数据库上没有插入/更新操作。我不知道为什么。我在我的工作簿 (myConn) 中建立了 SQL 连接,就像我每次需要连接 SQL 时所做的那样,所以它肯定是正确的。这是我的标准 VBA 代码:

Sub SaveData()

    Dim myValue As Double   
    myValue = Sheets("XYZ").Range("valueToSave").Value

    With ActiveWorkbook.Connections("myConn").OLEDBConnection
        .CommandText = Array( _
         "EXEC DB.[dbo].[myProc] '" & myValue & "'")
    End With

    ActiveWorkbook.Connections("myConn").Refresh
  
End Sub

我需要将数据插入decimal(6,4) 类型的列(在 SQL 表中)。 myProc 当我通过 SSMS 手动运行它而不是在这里使用 VBA 代码时,它做得很好。 valueToSave 是一个 Excel 范围,它存储一个十进制值(例如:23,5611,21 等)。当我运行宏时没有任何反应。当我运行宏并转到“连接属性”>“定义”>“命令文本”时,我可以看到有一个带有参数的过程(EXEC DB.[dbo].[myProc]'11,23')。所以我上面的代码似乎工作但没有执行存储过程。

与数据类型有关吗?老实说,我尝试过使用其他 VBA 类型:StringVariantInteger,但它不起作用。我还更改了 SQL 表中该列的数据类型(更改为 varcharint 等),但它也不起作用。最有趣的是,上面的代码在我从数据库中提取数据时可以正常工作,而在需要插入/更新数据时则无法正常工作。

PS。我想我添加了所有必需的参考:

【问题讨论】:

警告:您的代码很危险;它对 SQL 注入攻击很开放。修复您的代码,并parametrise 我在存储过程中使用参数。无论如何,代码是在我公司内部使用的。我只是想知道为什么插入/更新在这里不起作用 "EXEC DB.[dbo].[myProc] '" & myValue & "'"使用参数...即注入... “无论如何,代码是在我公司内部使用的” 这就像在说“我只把车停在我的住所和办公室外面,所以不锁车是安全的。 " 存储过程可能有参数,但你提交的SQL代码没有。考虑 Alice 在您的 Excel 单元格中输入如下内容:'; drop database DB; --。是时候阅读 OleDbCommand Parameters 并将该代码转换为 VBA。 【参考方案1】:

使用 ADODB

Option Explicit

Sub SaveData()

    Const PROC_NAME = "DB.dbo.myproc"

    Dim wb As Workbook
    Dim ado As ADODB.Connection, cmd As ADODB.Command
    Dim sCon As String, v As Single

    Set wb = ThisWorkbook
    v = wb.Sheets("XYZ").Range("valueToSave").Value
    
    ' get connection string
    sCon = wb.Connections("myConn").OLEDBConnection.Connection
    sCon = Replace(sCon, "OLEDB;", "")

    ' open connection
    Set ado = New ADODB.Connection
    ado.Open sCon

    Set cmd = New ADODB.Command
    With cmd
        .ActiveConnection = ado
        .CommandType = adCmdStoredProc
        .CommandText = PROC_NAME
        .Parameters.Append .CreateParameter("P1", adDecimal, adParamInput)
        With .Parameters(0)
            .NumericScale = 2
            .Precision = 18
            .Value = v
        End With
        .Execute
    End With
    ado.Close

    MsgBox PROC_NAME & " " & v, vbInformation, "Done"

End Sub

【讨论】:

以上是关于如何使用 VBA 执行插入/更新记录的存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

将本地数据插入 SQL Server 临时表

在执行动态插入脚本的情况下,如何在 MSSQL 存储过程中选择新插入的记录?

在 SQL Server 上插入更新存储过程

如何使用bigquery流将嵌套数据插入现有记录

带有连接的记录集不可更新 - 如何正确执行 VBA

一个存储过程中更新多个表可以用一个COMMIT吗 ?