【问题标题】:Stored procedure not returning recordset存储过程不返回记录集
【发布时间】:2017-05-06 02:27:44
【问题描述】:

我坚持以下。我有一个存储过程,它以日期和经理 ID 作为参数来生成结果集

CREATE PROCEDURE[ACT].[sp_getAllocations]
    @dtmReportDate DATE,
    @ManagerID BIGINT,
    @type nvarchar(MAX) OUTPUT
AS
BEGIN
    SELECT 
        ARCVTADMIN.tblEmployee.strFirstName + ' ' + ARCVTADMIN.tblEmployee.strSurname AS Name, 
        COUNT(ACT.tblActivity.employeeID) AS Workstate, 
        SUM(CASE WHEN ACT.tblactivity.statusTypeID = 4 AND ACT.tblActivity.dtmCompletedDate = @dtmReportDate THEN 1 ELSE 0 END) AS Completed, 
        SUM(CASE WHEN ACT.tblActivity.statusReasonID = 1 THEN 1 ELSE 0 END) AS NewLeads, 
        SUM(CASE WHEN ACT.tblContact.dtmLoggedDate = @dtmReportDate THEN 1 ELSE 0 END) AS Worked
    FROM            
        ACT.tblContact 
    RIGHT OUTER JOIN
        ACT.tblActivity ON ACT.tblContact.activityID = ACT.tblActivity.activityID 
    LEFT OUTER JOIN
        ARCVTADMIN.tblEmployee ON ACT.tblActivity.employeeID = ARCVTADMIN.tblEmployee.employeeID 
                               AND ACT.tblActivity.employeeID = ARCVTADMIN.tblEmployee.employeeID 
                               AND ACT.tblActivity.employeeID = ARCVTADMIN.tblEmployee.employeeID
                               AND ACT.tblActivity.employeeID = ARCVTADMIN.tblEmployee.employeeID
    GROUP BY 
        ARCVTADMIN.tblEmployee.strFirstName + ' ' + ARCVTADMIN.tblEmployee.strSurname, 
        ARCVTADMIN.tblEmployee.managerID
    HAVING        
        (ARCVTADMIN.tblEmployee.managerID = @ManagerID)
END

注意:ARCVTADMIN、ACT 是架构名称

当我在 SQL Server 中运行此存储过程时,它可以正常工作

Declare @D nVarchar(max);
EXECUTE ACT.sp_getAllocations @dtmReportDate = '20161220', @ManagerID = 91, @type=@D out
Print @D

以下是我在 SQL Server 中执行存储过程时产生的结果

Name            Workstate   Completed    NewLeads    Worked
===========================================================
Nikki Furnell     4999          0        3434           0
Harriet Johnson     10          0           0           0
Claire Rowe        138          0          17           0
Carina Hughes        4          0           0           0

我在类模块中有一个函数,如下所示

Public Function getSPRecordset(dtmReportDate As String, managerID As Long) As ADODB.Recordset
Dim strType As String
Dim rst As ADODB.Recordset
If Not (isConnectionOpen()) Then
OpenConnection
End If

Set ADOCom = New ADODB.Command
ADOCom.ActiveConnection = ADOConn
ADOCom.CommandType = adCmdStoredProc
ADOCom.CommandText = "[ACT].[sp_getAllocations]"
ADOCom.Parameters.Refresh

ADOCom.Parameters.Append ADOCom.CreateParameter("@dtmReportDate", adDate,   adParamInput, 10, dtmReportDate)
ADOCom.Parameters.Append ADOCom.CreateParameter("@ManagerID", adBigInt, adParamInput, 10, managerID)
ADOCom.Parameters.Append ADOCom.CreateParameter("@type", adVarChar, adParamOutput, 10000, strType)
Set rst = ADOCom.Execute
Set getSPRecordset = rst
End Function

我正在尝试检索结果集并将其分配给我的表单,我正在尝试以下操作。

Public Sub loadAllocation()
Dim objSS As clsSQLServer
Dim rst As ADODB.Recordset
Set objSS = New clsSQLServer
Set rst = objSS.getSPRecordset(Me.dtmReportDate, Me.managerID)
Set Me.frmTeamDashboardWorkstate.Form.Recordset = rst ***Error Line ****
set rst=nothing
End Sub

任何帮助将不胜感激

【问题讨论】:

  • 从哪里调用 loadAllocation?在这种情况下,Me 是什么? frmTeamDashboardWorkstate 是子表单吗?您是否希望此记录集在表单打开的所有时间都在网络上保持打开状态?如果没有,那么您应该使用“断开连接”的记录集。在设置之前使用rst.CursorLocation = adUseClient(可能需要将Dim 设置为New ADODB.Recordset 才能做到这一点)。
  • 旁注:您应该为您的存储过程使用sp_ 前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_ 并使用其他东西作为前缀 - 或者根本不使用前缀!
  • @Skippy 感谢您的回复。以下是澄清...
  • @Skippy 从哪里调用 loadAllocation?**从 OnChange 事件组合框 (ManagerID)** 在这种情况下,我是什么? frmTeamDashboardWorkstate 的父窗体 frmTeamDashboardWorkstate 是子窗体吗? 您是否希望此记录集在表单打开的所有时间都通过网络保持打开状态?如果没有,那么您应该使用“断开连接”的记录集。 不确定,但只需要显示数据在设置之前使用 rst.CursorLocation = adUseClient(可能需要将其调暗为 New ADODB.Recordset 才能执行此操作)。**仍然没有运气**
  • @marc_s 谢谢你的建议,一旦我完成了这个问题,我会做一个快速的 CTRL + H 事情......

标签: sql-server ms-access stored-procedures vba ms-access-2010


【解决方案1】:

好吧,我认为你需要做的是……

首先,您的Public Sub loadAllocation() 是在单独的模块中还是在父表单的模块中?我建议将其作为 Private Sub 放在父表单的模块中。

其次,您需要在父表单的模块中将 rst 声明为模块级变量。在loadAllocation() 运行后,它需要保持在范围内。所以在模块的顶部,在任何 Sub 或 Function 定义之前,在 Option Compare DatabaseOption Explicit 之后,添加

Private rst As ADODB.Recordset

然后我会将您的程序重新编码为

Private Sub loadAllocation()
On Error GoTo PROC_ERR

    Dim objSS As New clsSQLServer

    Set rst = New ADODB.Recordset
    rst.CursorLocation = adUseClient
    Set rst = objSS.getSPRecordset(Me.dtmReportDate, Me.managerID)
    'You could put some Debug.Print statements in here just to check that rst has retrieved some data'
    If rst.State = adStateOpen Then
        Set Me.frmTeamDashboardWorkstate.Form.Recordset = rst
        frmTeamDashboardWorkstate.Form.Requery
        rst.ActiveConnection = Nothing
    End If

PROC_EXIT:
    'Put any clean-up code in here'
    Exit Sub

PROC_ERR:
    'Put your preferred error handling code in here'
    Resume PROC_EXIT

End Sub

确保在关闭父表单时清理并Set rst = Nothing(在 Form_Unload 事件中)。

【讨论】:

    【解决方案2】:

    您使用的是 32 位还是 64 位 Access?如果你使用的是32位,那么bigint是64位的,32位访问无法处理。

    【讨论】:

      猜你喜欢
      • 2019-04-20
      • 1970-01-01
      • 2014-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      相关资源
      最近更新 更多