【问题标题】:Execute Stored Procedure with RollbackTrans using VBA and SQL Server 2012使用 VBA 和 SQL Server 2012 使用 RollbackTrans 执行存储过程
【发布时间】:2017-01-18 05:50:17
【问题描述】:

我想使用 VBA Excel 执行插入存储过程,但我遇到了一些问题。基本上,我想通过执行存储过程 10 次来插入 100 行相同的数据,并能够回滚事务。

  • 如果我执行 VBA 运行我的 VBA 代码而不使用 For 循环,那么我的 VBA 代码运行良好,没有错误
  • 当我插入 For 循环时,我得到一个错误,表明我有太多的协议。我试图移动 For 循环,但问题无法解决。

过程或函数 Sample 指定的参数过多。
-2147217900 关闭对象时不允许操作。 3704

我的问题:如何运行具有回滚事务能力的插入存储过程?或者我是否必须在我的 SQL Server 存储过程中编辑Rollback Trans ~~> 如果是这样,我该如何重写我的代码来执行新的 SQL?

我有一张桌子Test.Sample

Create Table Test.Sample
(
    ID int identity(1,1) primary key,
    Col1 varchar(10),
    Col2 varchar(10)
)

用下面的存储过程插入数据

CREATE PROCEDURE Sample
    @Col1 varchar(10),
    @Col2 varchar(10)
AS
   SET NOCOUNT ON

    INSERT INTO [Test].[Sample] (Col1, Col2)
    VALUES (@Col1, @Col2)

当我运行单个插入时,以下代码可以正常工作

Private Sub Test()
                    Dim con As ADODB.Connection
                    Dim cm As ADODB.Command
                    Set con = New ADODB.Connection
                    Set cm = New ADODB.Command
                    Dim pm As ADODB.Parameter
                    Dim i As Integer
On Error GoTo 1
                    con.Open connString
                    con.BeginTrans
'For i = 1 To 10 ~~~~ code will return an error if this is active
                    With cm
                    .ActiveConnection = con
                    .CommandType = adCmdStoredProc
                    .CommandText = "sales.spInsertSalesRequestPart"
                        .Parameters.Append .CreateParameter("@Col1", adVarChar, adParamInput, 10, "TEST")
                        .Parameters.Append .CreateParameter("@Col2", adVarChar, adParamInput, 10, "TEST")
                        .Execute
                   End With

'Next i
                   con.CommitTrans
                   con.Close
                   Exit Sub

1:
        With con
            con.RollbackTrans
            con.Close
        End With
    End If
End Sub

【问题讨论】:

  • 你能发布实际的错误编号和描述吗?另外,尝试将For 循环包装在开始并提交事务之外。
  • @Parfait 我添加了错误代码,但是,假设当我将 for 循环放在 BeginTrans 之前和下一个 CommitTrans 之后它可以工作,它会破坏 RollbackTrans 的目的吗?
  • 令我惊讶的是,即使执行一次代码也能正常工作,因为您有两个名为“@Col1”的参数,而没有一个名为“@Col2”的参数。但也许它并不真正关心名称是什么(我从未使用过参数,所以我绝对不是专家!),虽然我怀疑第二次通过循环有 4 个参数(当时有 20 个)您通过循环到达第 10 次)是导致问题的原因。
  • @yowE3K,这是一个错字
  • 如果“Col1”的重复是一个错字,那么我现在确信您的问题是您的循环首先传递 2 个参数(有效)然后传递 4 个参数(失败)然后传递 6 个参数等,而存储过程只需要 2 个参数。因此,您需要在添加新参数之前删除现有参数,否则只需使用.CommandText = "INSERT INTO [Test].[Sample] (Col1, Col2) VALUES ('" & valOfCol1 & "', '" & valOfCol2 & "')"(其中 valOfCol1 和 valOfCol2 是包含您要传递的值的字符串变量)。

标签: sql-server excel tsql transactions vba


【解决方案1】:

如果你要使用相同的参数,那么你可以在 sql 过程本身中使用事务并进行循环

CREATE PROCEDURE Sample
@Col1 varchar(10),
@Col2 varchar(10)
AS
SET NOCOUNT ON

begin tran
declare @i int = 1
while @i <= 10 
begin
INSERT INTO [Test].[Sample] (Col1, Col2)
VALUES (@Col1, @Col2)
set @i=@i+1
end
commit tran

但我确信您可能有不同的变量要从您的 vb 或 c# 传递给每个循环,在这种情况下,您可以将所有变量打包到一个表变量中并将其作为单个表变量传递,您可以在 sproc 中进行事务

【讨论】:

  • 是的,示例代码只是为了简化问题,Col1 和 Col2 每次的体积都会不同。太糟糕了,我仅限于 VBA Excel。
【解决方案2】:

考虑在每次迭代时重置命令对象cmd。作为@YowE3K cmets,您越来越多地向每个调用附加参数,因此错误参数太多

...
con.BeginTrans

For i = 1 To 10
    Set cm = New ADODB.Command

    With cm
       .ActiveConnection = con
       .CommandType = adCmdStoredProc
       .CommandText = "sales.spInsertSalesRequestPart"
       .Parameters.Append .CreateParameter("@Col1", adVarChar, adParamInput, 10, "TEST")
       .Parameters.Append .CreateParameter("@Col2", adVarChar, adParamInput, 10, "TEST")
       .Execute
    End With

Next i

con.CommitTrans
...

【讨论】:

  • 谢谢,其实我之前就想通了,几个小时前去看了我的医生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-03
  • 2015-11-20
  • 2016-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
相关资源
最近更新 更多