提问人:Lumpi 提问时间:10/5/2011 最后编辑:Lumpi 更新时间:1/5/2017 访问量:15045
ADODB 打开记录集失败/“关闭对象时不允许操作”
ADODB open recordset fails / "Operation is not allowed when object is closed"
问:
我在excel中有以下UDF,它使用ADO连接到我的MSSQL服务器。在那里,它应该执行标量 udf “D100601RVDATABearingAllow”。
由于某种原因,我尝试追加的参数没有发送到 sql server。仅在服务器上:
SELECT dbo.D100601RVDATABearingAllow
到达。
我的 EXCEL UDF:
Function RVDATA(Fastener) As Long
Dim cnt As ADODB.Connection
Dim rst As ADODB.Recordset
Dim Cmd1 As ADODB.Command
Dim stSQL As String
Const stADO As String = "Provider=SQLOLEDB.1;Data ................"
'----------------------------------------------------------
Set cnt = New ADODB.Connection
With cnt
.ConnectionTimeout = 3
.CursorLocation = adUseClient
.Open stADO
.CommandTimeout = 3
End With
'----------------------------------------------------------
Set Cmd1 = New ADODB.Command
Cmd1.ActiveConnection = cnt
Cmd1.CommandText = "dbo.D100601RVDATABearingAllow"
Cmd1.CommandType = adCmdStoredProc
'----------------------------------------------------------
Set Param1 = Cmd1.CreateParameter("Fastener", adInteger, adParamInput, 5)
Param1.Value = Fastener
Cmd1.Parameters.Append Param1
Set Param1 = Nothing
'----------------------------------------------------------
Set rst = Cmd1.Execute()
RVDATA = rst.Fields(0).Value
'----------------------------------------------------------
rst.Close
cnt.Close
Set rst = Nothing
Set cnt = Nothing
'----------------------------------------------------------
End Function
当我使用 adCmdStoredProc 时,整个事情都失败了,并且在 vba 调试器中,记录集的属性有很多“关闭对象时不允许操作”(听起来可能有点不同,消息被翻译)
当我不使用 adCmdStoredProc 时,我收到未提供变量 Fastener 的消息。
我认为我打开记录集的方式可能有问题。 在其他踏板中,我读到有关使用“SET NOCOUNT ON”选项的信息,但这也没有用。
有人有想法吗? 问候 Lumpi
答:
您不需要服务器端功能,只需提供其名称(“[tra-CAE400-1].dbo.D100601RVDATABearingAllow)。
此外,还应将该属性设置为“stored-procedure”(w3schools.com 上的属性引用)。SELECT
.CommandText
.CommandType
然后 adodb 就会知道你说的是调用一个函数,而不是试图发送一个普通的 sql 命令。
然后,它很可能允许您在命令对象上定义参数。 但是,在命令对象上定义的参数应(在名称和类型上)与定义为 SQL Server 中函数参数的参数完全对应。
microsoft.com 中关于将命令对象与存储过程一起使用的示例
评论
也遇到了这个错误(就我而言,我正在使用存储过程来检索一些信息)。我做了一些更改,导致执行失败。
当我将 SET NOCOUNT ON 作为存储过程的第一个语句时,错误消失了。
我也遇到了一个存储过程。您是否设置了 NOCOUNT = OFF;在代码的底部?经过大量的谷歌搜索后,这就是对我有用的东西。此外,如果您有任何其他运行的代码,则必须将其包装在 Nocount = on/off, INCLUDING insert 和 update 语句中。你可能会认为插入语句无关紧要,但以这种方式包装代码是阻止我今天自杀的原因。
另一个可能的原因是调试语句。我只是花了太长时间试图弄清楚为什么这对我不起作用,数据库上的 Proc 工作正常,应该插入的数据入,VBA 代码工作正常,但记录集中什么都没有。 最终的解决方案是遍历已构建的进程并删除 PRINT 语句。 若要测试这是否是问题所在,请在 SQL Server 上手动运行过程,然后查看结果的“消息”选项卡,如果除了“命令已成功完成”之外还有其他内容。 您需要消除这些消息。“SET NOCOUNT ON”将删除行计数消息,但可能还有其他消息。
我假设 5 年后 OP 已经解决了这个特定问题,所以这只适用于像我这样在寻找相同问题时发现这个问题的人。
在我们的商店中,我们经常在存储过程中使用这样的行来帮助调试:
RAISERROR('Debug message here',0,1) WITH NOWAIT;
这也中断了在 Excel vba 中打开记录集。我相信这个问题的完整答案是,在存储过程中:
- 使用 SET ROWCOUNT OFF
- 删除所有 PRINT 语句
- 删除所有用于调试的 RAISEERROR 语句(即严重性为 0)
评论