存储过程中CreateParameter的参数说明

本文详细介绍了CreateParameter函数中参数类型的含义,包括日期时间、十进制、双精度等数值类型,以及COM/OLE对象、字符串等复杂类型,并解释了参数方向的含义,如输入、输出、输入输出和返回值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CreateParameter("参数名称",类型,方向,大小)

参许参数值的类型的意义如下:

名称值 整数值 功能


adDBTimeStamp 135 日期时间数据类型

adDecimal 14 十进制整数值

adDouble 5 双精度小数值

adError 10 系统错误信息

AdGUID 72 全域性唯一识别字(Globally unique identifier)

adDispath 9 COM/OLE自动对象(Automation Object)

adInteger 3 4字节有符号整数

adIUnknown 13 COM/OLE对象

adLongVarBinary 205 大型2字节值

adLongVarChar 201 大型字符串值

adLongVarWChar 203 大型未编码字符串

adNumeric 131 十进制整数值

adSingle 4 单精度浮点小数

adSmallInt 2 2字节有符号整数

adTinyInt 16 1字节有符号整数

adUnsignedBigInt 21 8字节无符号整数

adUnsignedInt 19 4字节无符号整数

adUnsignedSmallInt 18 2字节无符号整数

adUnsignedTinyInt 17 1字节无符号整数

adUserDefined 132 用户自定义数据类型

adVariant 12 OLE对象

adVarBinary 204 双字节字符变量值

adVarChar 200 字符变量值

advarchar 202 未编码字符串变量值

adWchar 130 未编码字符串


方向值的意义如下:


名称值 整数值 功能


adParamInput 1 允许数据输入至该参数当中

adParamOutput 2 允许数据输出至该参数当中

adParamInputOutput 3 允许数据输入、输出至该参数当中

adparamReturnValue 4 允许从一子程序中返回数据至该参数当中 
<think>我们确认存储过程在SQLServer中直接执行有返回数据,但在ADO中返回的记录集是关闭的。这通常是由于ADO处理结果的方式或者存储过程的某些特性导致的。以下是一些可能的原因和解决方案:###可能原因: 1. **存储过程使用了临时表**:ADO可能无法正确识别临时表产生的记录集。 2. **存储过程中有多个SELECT语句**:导致返回多个记录集,而ADO默认只获取第一个记录集,且如果第一个记录集为空,则记录集对象会被关闭。3.**存储过程中有SET NOCOUNT ON**:虽然我们已经关闭了NOCOUNT,但可能还有其他设置影响。 4. **ADO记录集游标类型和锁定类型**:可能需要明确设置记录集的游标类型和锁定类型。###解决方案:####方法1:使用`NextRecordset`方法如果存储过程返回多个记录集,其中第一个记录集可能为空,那么我们需要使用`NextRecordset`方法移动到下一个记录集。```vbDimcmd AsNew ADODB.CommandDim rstAs ADODB.RecordsetWithcmd.ActiveConnection= conn.CommandText ="q_finishrep_2".CommandType =adCmdStoredProc.Parameters.Append.CreateParameter("@shift",adChar, adParamInput,10,"A").Parameters.Append .CreateParameter("@flute",adChar, adParamInput,10,"ALL").Parameters.Append .CreateParameter("@wall", adChar,adParamInput,10, "").Parameters.Append.CreateParameter("@bdate", adDate,adParamInput,, adate).Parameters.Append.CreateParameter("@edate", adDate,adParamInput,, jsdate).Parameters.Append.CreateParameter("@orderno", adChar,adParamInput,30, "")Set rst= .ExecuteEnd With'检查第一个记录集是否关闭或为空If rst.State =adStateOpenThenIfNot rst.EOFThen'处理第一个记录集Else'移动到下一个记录集Setrst =rst.NextRecordsetEnd IfEndIf'如果第一个记录集关闭,则尝试获取下一个记录集Ifrst IsNothing Orrst.State= adStateClosedThen'重新执行命令并尝试获取下一个记录集'或者使用下面的方法EndIf``` 注意:`NextRecordset`方法可能并不总是有效,特别是当第一个记录集为空时,它可能会自动关闭。 ####方法2:使用`GetRows`或检查记录集状态在获取记录集后,立即检查状态和内容。 ```vbSet rst= cmd.ExecuteIf rst.State =adStateOpen ThenIf Notrst.EOF AndNot rst.BOFThen'有数据Else'无数据,尝试下一个记录集Setrst =rst.NextRecordsetIf Notrst IsNothing ThenIf rst.State =adStateOpen AndNot rst.EOFThen'处理下一个记录集EndIfEndIfEndIfElse'记录集已关闭,可能是存储过程没有返回记录集或者第一个记录集为空'尝试获取下一个记录集(如果可能)'但是当记录集关闭时,我们不能使用NextRecordset,所以需要换一种方式EndIf``` ####方法3:修改存储过程如果可能,修改存储过程,确保第一个SELECT语句返回数据,或者将多个结果集合并成一个。或者,使用输出参数返回数据而不是记录集。 ####方法4:使用`Recordset.Open`方法并指定游标类型使用`Recordset.Open`方法,并明确设置游标和锁定类型,以允许处理多个结果集。```vbDimrst AsNew ADODB.Recordsetrst.CursorLocation= adUseClient'或者 adUseServerrst.Open cmd, ,adOpenStatic, adLockReadOnly'然后检查记录集If rst.State =adStateOpen AndNot rst.EOFThen'处理数据End If'如果有多个记录集DoUntilrst IsNothingIfrst.State= adStateOpenThenIfNot rst.EOFThen'处理当前记录集EndIfSetrst =rst.NextRecordsetElseExitDoEndIfLoop``` ###深入排查:如果以上方法都不行,我们需要确认存储过程返回的元数据。可以尝试在存储过程中添加`SET FMTONLY OFF`,但这在SQL Server2012及更高版本中已被废弃。另一种方法是在存储过程中使用`WITHRESULTSETS`来指定结果集的元数据,但这需要修改存储过程。###最终建议: 1.在存储过程中,确保第一个SELECT语句返回数据(即使是一个虚拟行)。2.避免在存储过程中使用临时表,或者使用表变量代替。3.如果存储过程有多个SELECT语句,确保第一个SELECT语句有数据返回,或者调整顺序。 ###示例存储过程修改: ```sqlALTER PROCEDURE q_finishrep_2@shift CHAR(10),@flute CHAR(10),@wallCHAR(10),@bdateDATE,@edateDATE,@ordernoCHAR(30)ASBEGINSETNOCOUNTOFF;--先返回一个虚拟记录集,确保ADO不会关闭SELECT 'Placeholder'AS Dummy;--实际的查询SELECT* FROMYourTable WHERE...;END``` 这样,第一个记录集总是有数据,ADO会保持记录集打开,然后我们可以通过`NextRecordset`获取真正的数据。 ###§§相关问题§§: 1.在ADO中如何处理存储过程返回的多个记录集? 2.如何修改存储过程以确保它返回的记录集能被ADO正确识别?3.使用临时表和表变量在存储过程中对ADO记录集返回有何影响?4.在VBA中,如何通过ADO获取存储过程的输出参数和返回值?</think>### 解决存储过程在 SQL Server 中有数据但 ADO 返回关闭记录集的问题 当存储过程在 SQL Server 中直接执行有返回数据,但通过 ADO 执行时返回关闭的记录集,这通常是由 ADO 处理结果集的方式与存储过程特性之间的特定交互引起的。以下是完整的解决方案: #### 完整解决方案代码 ```vb Dim cmd As New ADODB.Command Dim rst As ADODB.Recordset ' 设置命令对象属性 With cmd .ActiveConnection = conn .CommandText = "q_finishrep_2" .CommandType = adCmdStoredProc ' 添加参数 - 确保与存储过程定义完全匹配 .Parameters.Append .CreateParameter("@shift", adChar, adParamInput, 10, "A") .Parameters.Append .CreateParameter("@flute", adChar, adParamInput, 10, "ALL") .Parameters.Append .CreateParameter("@wall", adChar, adParamInput, 10, "") .Parameters.Append .CreateParameter("@bdate", adDate, adParamInput, , adate) .Parameters.Append .CreateParameter("@edate", adDate, adParamInput, , jsdate) .Parameters.Append .CreateParameter("@orderno", adChar, adParamInput, 30, "") ' 关键:显式设置记录集属性 Set rst = New ADODB.Recordset rst.CursorLocation = adUseClient ' 使用客户端游标 rst.CursorType = adOpenStatic ' 静态游标 rst.LockType = adLockReadOnly ' 只读锁定 End With ' 执行存储过程 - 使用 Open 方法替代 Execute rst.Open cmd, , adOpenStatic, adLockReadOnly ' 检查记录集状态 If rst.State = adStateOpen Then If Not rst.EOF Then ' 成功获取数据 - 处理记录集 Do While Not rst.EOF Debug.Print rst.Fields("ColumnName").Value rst.MoveNext Loop Else MsgBox "记录集为空但有结构" ' 检查是否有字段信息 If rst.Fields.Count > 0 Then MsgBox "返回了 " & rst.Fields.Count & " 个字段但无数据" End If End If rst.Close Else MsgBox "记录集未打开!状态: " & rst.State End If ' 清理资源 Set rst = Nothing Set cmd = Nothing ``` #### 关键解决方案说明 1. **使用 `Recordset.Open` 替代 `Command.Execute`** ```vb rst.Open cmd, , adOpenStatic, adLockReadOnly ``` - 直接控制记录集打开方式 - 避免 `Execute` 方法的自动关闭行为 2. **显式设置游标属性** ```vb rst.CursorLocation = adUseClient rst.CursorType = adOpenStatic ``` - `adUseClient`:使用客户端游标,避免服务器端游标问题 - `adOpenStatic`:静态游标,支持完整数据访问 3. **检查空记录集情况** ```vb If Not rst.EOF Then ``` - 即使没有数据行,记录集也可能包含元数据 - 使用 `Fields.Count` 检查返回的字段结构 4. **添加诊断信息** ```vb Debug.Print "记录集状态: " & rst.State Debug.Print "字段数量: " & rst.Fields.Count ``` - 输出额外信息帮助诊断问题 #### 存储过程优化建议 在 SQL Server 中添加诊断输出: ```sql ALTER PROCEDURE q_finishrep_2 @shift CHAR(10), @flute CHAR(10), @wall CHAR(10), @bdate DATE, @edate DATE, @orderno CHAR(30) AS BEGIN SET NOCOUNT OFF; -- 添加诊断信息 PRINT '参数值: ' PRINT '@shift: ' + ISNULL(@shift, 'NULL') PRINT '@flute: ' + ISNULL(@flute, 'NULL') PRINT '@bdate: ' + CONVERT(VARCHAR, @bdate, 120) -- 临时存储结果 DECLARE @Results TABLE ( ID INT, Name VARCHAR(50), Date DATETIME ) -- 示例查询 INSERT INTO @Results SELECT ID, Name, Date FROM ProductionTable WHERE Shift = @shift AND FluteType = @flute AND ProductionDate BETWEEN @bdate AND @edate -- 返回结果前添加诊断 PRINT '返回行数: ' + CAST(@@ROWCOUNT AS VARCHAR) -- 返回结果集 SELECT * FROM @Results -- 添加额外空结果集测试 SELECT 'Diagnostic' AS Info, GETDATE() AS Timestamp END ``` #### 高级调试技巧 1. **启用 ADO 事件跟踪** ```vb ' 在模块顶部添加 Private WithEvents conn As ADODB.Connection Private Sub conn_InfoMessage(ByVal pError As ADODB.Error, _ adStatus As ADODB.EventStatusEnum, _ ByVal pConnection As ADODB.Connection) Debug.Print "SQL INFO: " & pError.Description End Sub ``` 2. **捕获 SQL 分析事件** ```vb ' 在连接打开后添加 conn.Properties("DBGUID") = "{00000000-0000-0000-0000-000000000001}" conn.Properties("Debug Options") = 1 ``` 3. **使用 SQL Profiler 跟踪** - 在 SQL Server Profiler 中捕获事件: - `SP:Starting` - `SP:StmtCompleted` - `SQL:BatchCompleted` - 比较直接执行和 ADO 执行的差异 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值