Access 365调用SQL存储过程遇参数错误及排查解决
更新2: 呃……我可能忘了取消这行的注释……
If Not IsMissing(Arg1) Then cmd.CreateParameter(1, adVarChar, adParamInput) = Arg1 'cmd.Parameters(1) = Arg1 <-- End If
取消注释后的首次运行成功了……这是个好迹象。我会继续测试并反馈。之前添加CreateParameter行时,我没有检查用户权限,这可能是问题所在。结合这两点,问题可能已解决,敬请关注!
更新:
添加以下代码后出现新错误:-2147217911 对象的EXECUTE权限被拒绝 -2147217904 存储过程或函数'DW_LocalAccount_Read'需要参数'@RowID',但未提供。
我查看了存储过程所在服务器上Access数据库使用的用户,该用户原本有读写权限,我为测试赋予了所有者权限,之后错误变为:-2147217904 存储过程或函数'DW_LocalAccount_Read'需要参数'@RowID',但未提供。
这缩小了排查范围,我需要找出参数未传递的原因。
If Not IsMissing(Arg1) Then cmd.CreateParameter(1, adVarChar, adParamInput) = Arg1 <-- 'cmd.Parameters(1) = Arg1 End If
我花了一天半时间查阅数百篇关于“Object Required”和“集合中找不到请求的名称或序号对应的项”错误的帖子,但没有找到完全匹配我问题的内容。
我接手了一份离职人员留下的Access 365数据库,其中有一个存储客户数据的表单,数据通过SQL Server的存储过程获取。Access前端用户要求当Ship3为空时,将Ship1的数据填入Ship3。我在存储过程中添加了CASE语句实现该功能,且存储过程本身运行正常。
但回到Access前端后,代码在以下行抛出Object Required错误:
Set rsLocal = FormHandling.GetFormRecordset("DW_LocalAccount_Read", RowID)
我原本以为是存储过程出错,验证了所有列的提取顺序、名称均正确,结果集与之前一致(仅Ship3有变化)。于是我换回旧版本的存储过程,但此时旧版本也无法正常运行了。
随后我在Access中逐步调试,发现错误始于以下代码行:
If Not IsMissing(Arg1) Then cmd.Parameters(1) = Arg1 <-- End If
执行该行时出错,回到最初的Set语句并抛出Object Required错误。我添加消息框查看错误,得到的错误信息是“3265 集合中找不到请求的名称或序号对应的项”。
完整的函数代码如下:
Public Function GetFormRecordset(CommandText As String, Optional Arg1 As Variant, Optional Arg2 As Variant, Optional Arg3 As Variant, Optional Arg4 As Variant, Optional Arg5 As Variant) As Variant On Error GoTo Function_Error Dim cmd As New ADODB.Command Dim rs As New ADODB.Recordset Dim parm As ADODB.Parameter Dim rsDBO As DAO.Recordset cmd.CommandType = adCmdStoredProc cmd.NamedParameters = True cmd.Prepared = True cmd.CommandText = CommandText Set cmd.ActiveConnection = DWDB cmd.Parameters.Refresh If Not IsMissing(Arg1) Then cmd.Parameters(1) = Arg1 End If If Not IsMissing(Arg2) Then cmd.Parameters(2) = Arg2 End If If Not IsMissing(Arg3) Then cmd.Parameters(3) = Arg3 End If If Not IsMissing(Arg4) Then cmd.Parameters(4) = Arg4 End If If Not IsMissing(Arg5) Then cmd.Parameters(5) = Arg5 End If Set rs = New ADODB.Recordset With rs .CursorLocation = adUseClient .CursorType = adOpenKeyset '.LockType = adLockOptimistic .LockType = adLockReadOnly .Open cmd .MoveLast .MoveFirst End With Set GetFormRecordset = rs Function_Exit: On Error Resume Next 'rs.Close 'Set cmd = Nothing 'rsDBO.Close 'Set rsDBO = Nothing On Error GoTo 0 Exit Function Function_Error: If Err.Number = 3709 Then 'no valid conn Set GetFormRecordset = Nothing ElseIf Err.Number = 3021 Then 'EOF/BOF Resume Next End If End Function
我对参数和集合操作不太熟悉,查阅资料后尝试在“=arg1”前添加参数追加操作,但没有效果。我感到困惑:为何原本正常的存储过程,仅修改列数据填充逻辑后就出现问题?为何未修改Access代码,换回原存储过程后也无法运行?希望能得到帮助,我现在一筹莫展。
另外附上原始存储过程代码:
USE [DB] GO /****** Object: StoredProcedure [dbo].[DW_LocalAccount_READ] Script Date: 8/16/2022 11:31:39 AM ******/ DROP PROCEDURE [dbo].[DW_LocalAccount_READ] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[DW_LocalAccount_READ] @RowID as Varchar(38) AS SET NOCOUNT ON BEGIN TRY BEGIN SELECT RBCCustDtl.* FROM RBCCustDtl WITH(NOLOCK) Where ( RBCCustDtl.RBCCustDtlCustDtlRowID = Cast(@Rowid as uniqueidentifier) Or @RowID = '' ) END END TRY BEGIN CATCH IF @@ERROR <> 0 BEGIN Return null END END CATCH GO
内容的提问来源于stack exchange,提问作者byteme

