原生ADO(Recordset,Command)执行存储过程(100分)

  • 主题发起人 主题发起人 ygw531
  • 开始时间 开始时间
Y

ygw531

Unregistered / Unconfirmed
GUEST, unregistred user!
Recordset在执行存储过程的时候如果这个存储过程有创建临时表,插入,更新等操作的时候在返回数据的时候提示:“recordset is not open”。<br>如果该存储过程只是一些select语句的时候就没有问题。recordset打开数据集的方法: &nbsp;try<br>&nbsp; &nbsp; ConnectionPools.CreateInstance(vConnection);<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; aRecordset:= CoRecordset.Create;<br>&nbsp; &nbsp; &nbsp; aRecordset.CursorLocation := adUseClient;<br>&nbsp; &nbsp; &nbsp; aRecordset.Open(SSQL,vConnection,adOpenForwardOnly,adLockReadOnly,adCmdText);<br>&nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; aRecordSet := nil;<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; if vConnection &lt;&gt; nil then<br>&nbsp; &nbsp; &nbsp; ConnectionPools.ReleaseInstance(vConnection);<br>&nbsp; end;<br><br>用command对象,command对象没用过,不知道怎么用,不知道参数怎么拼合 ,command的方法:command.execute(aRecordsAffected,Parameters,option);执行完后返回的数据集怎么赋给recordset。<br>注:存储过程最后都会有一个select返回一个数据集。<br><br>说明:要求只需要用原生对象处理,不想用显性的ado控件,存在必有道理这个不要问为什么。我想知道是原生对象怎么处理这类情况。网上找了很多资料都没找到合适的。
 
换一种试试 从 _COMMAND中返回看看<br>&nbsp; &nbsp;u_CommandAll:_Command; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //命令执行器<br><br>&nbsp; u_CommandAll.Parameters.Delete(0);<br>&nbsp; u_CommandAll.CommandText:=SQLStatement;<br>&nbsp; Recordset:=u_CommandAll.Execute(RecordsAffected, EmptyParam, 0);<br>&nbsp; Recordset.Set_ActiveConnection(nil);
 
1、//存储过程参数结构,只定义了常用的部分,如果需要自己加吧<br>type<br>&nbsp; TParameter_ = record<br>&nbsp; &nbsp; Name: WideString;<br>&nbsp; &nbsp; Type_: LongWord;<br>&nbsp; &nbsp; Direction: LongWord;<br>&nbsp; &nbsp; Size: Longint;<br>&nbsp; &nbsp; Value: OleVariant;<br>&nbsp; end;<br><br>&nbsp; TParameters_ = array of TParameter_;<br><br>//cnn 是 Connection对象,cmd 是 Command 对象,rst 是 Recordset 对象,prc 是存储过程命令行,prms 是参数集合<br>function ExecProc(cnn, cmd, rst: OleVariant; const prc: string; prms: TParameters_): Boolean;<br>var<br>&nbsp; i: Longint;<br>begin<br>&nbsp; Result := not (VarIsEmpty(cnn) or VarIsEmpty(cmd)) and (cnn.State = adStateOpen);<br>&nbsp; if Result then<br>&nbsp; begin<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; cmd.CommandText := prc;<br>&nbsp; &nbsp; &nbsp; cmd.CommandType := adCmdStoredProc;<br>&nbsp; &nbsp; &nbsp; cmd.ActiveConnection := cnn;<br><br>&nbsp; &nbsp; &nbsp; //之前,将我们自己的参数集合中的输入参数添入 Command 参数集合<br>&nbsp; &nbsp; &nbsp; for i := Low(prms) to High(prms) do<br>&nbsp; &nbsp; &nbsp; &nbsp; case prms.Direction of<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //未知类型的参数(adParamUnknown)既不算作输入参数也不算作输出参数<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; adParamInput, adParamInputOutput:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cmd.Parameters[prms.Name].Value := prms.Value;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; &nbsp; rst := cmd.Execute;<br><br>&nbsp; &nbsp; &nbsp; //之后,将输出参数从 Command 参数集合读取到我们自己的参数集合<br>&nbsp; &nbsp; &nbsp; for i := Low(prms) to High(prms) do<br>&nbsp; &nbsp; &nbsp; &nbsp; case prms.Direction of<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //未知类型的参数(adParamUnknown)既不算作输入参数也不算作输出参数<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; adParamOutput, adParamInputOutput:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prms.Value := cmd.Parameters[prms.Name].Value;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; adParamReturnValue:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prms.Value := cmd.Parameters[0].Value;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; Result := False;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br>2、下面是一个例子:<br>//执行存储过程<br>(*<br>CREATE PROCEDURE GetProductName<br>&nbsp; &nbsp; @ProductID int,<br>&nbsp; &nbsp; @ProductName varchar(50) OUTPUT<br>AS<br>SELECT @ProductName = ProductName<br>FROM Products<br>WHERE ProductID = @ProductID<br>RETURN @ProductID<br>*)<br>procedure TForm1.Button3Click(Sender: TObject);<br>var<br>&nbsp; prms: TParameters_;<br>begin<br>&nbsp; SetLength(prms, 3);<br>&nbsp; //参数 0 接收返回值;Name 取什么都行,但 Direction 必须标明为adParamReturnValue<br>&nbsp; prms[0].Name := '@RETURN_VALUE';<br>&nbsp; prms[0].Direction := adParamReturnValue;<br>&nbsp; //参数 1 作为输入参数,Name 必须与实际参数名相同,Direction 标明 adParamInput<br>&nbsp; prms[1].Name := '@ProductID';<br>&nbsp; prms[1].Direction := adParamInput;<br>&nbsp; prms[1].Value := 8;<br>&nbsp; //参数 2 作为输出参数,Name 必须与实际参数名相同,Direction 标明 adParamOutput<br>&nbsp; prms[2].Name := '@ProductName';<br>&nbsp; prms[2].Direction := adParamOutput;<br>&nbsp; //执行存储过程;如果不需要 Recordset 对象接收返回的数据集,就把它置空<br>&nbsp; ExecProc(cnn, cmd, Null, 'GetProductName', prms);<br>&nbsp; ShowMessage(prms[0].Value);<br>&nbsp; ShowMessage(prms[2].Value);<br>end;<br>3、更多更具体的见我的文章,里面说的很清楚。以后要多看 vvyang 的文章,谢谢!<br>http://www.delphibbs.com/delphibbs/dispq.asp?lid=3047846
 
VVyang的文章我看过,感觉拼参数太麻烦,所以没有采用。fhli的我已经试过。但是那个参数怎么处理。
 
fhli返回的recordset我用的是_Recordset接收,但是输出来的时候提示说是关闭的对象
 
function ExecSQLData(StoredProcName: WideString; var aRecordset: _Recordset): Boolean;<br>var<br>&nbsp; vConnection: ADODB_TLB._Connection;<br>&nbsp; aCommand:_Command;<br>&nbsp; aRff:OleVariant;<br>begin<br>&nbsp; Result := False;<br>&nbsp; try<br>&nbsp; &nbsp; ConnectionPools.CreateInstance(vConnection);<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; aCommand:= CoCommand.Create;<br>&nbsp; &nbsp; &nbsp; aRecordset:= CoRecordset.Create;<br>&nbsp; &nbsp; &nbsp; aCommand.Set_ActiveConnection(vConnection);<br>&nbsp; &nbsp; &nbsp; aRecordset.Set_ActiveConnection(vConnection);<br>&nbsp; &nbsp; &nbsp; acommand.CommandText:=StoredProcName;<br>&nbsp; &nbsp; &nbsp; acommand.CommandType := adCmdStoredProc;<br>&nbsp; &nbsp; &nbsp; aRecordset:= aCommand.Execute(aRff,EmptyParam,0);<br>&nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; aRecordSet := nil;<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; if vConnection &lt;&gt; nil then<br>&nbsp; &nbsp; &nbsp; ConnectionPools.ReleaseInstance(vConnection);<br>&nbsp; end;<br>end;
 
顺便发个交流群:delphi天堂群:4654765,不去是你的损失 &nbsp;,长期不发言者勿入
 
To ygw531:<br>&nbsp; 原生 ADO 存储过程的参数就是这么传递的,另外我写的是通用过程,程序是死的人是活的,您可以针对自己的情况用静态数组直接把参数集合声明出来。<br>给你两个建议:<br>1、如果您不需要参数,可以把 prms: TParameters_ 置为 Null,甚至可以直接把拼参数的代码去掉。依您的水平这点应该能看出来。<br>2、无参数的存储过程 Recordset 也能胜任,不一定非要 Command。至于怎么做我不想跟您浪费口舌了。<br>3、我实在看不出来 fhli 和您自己写的程序哪里能传递参数、哪里能返回参数?我很想知道您是如何做到参数传递和接收的,谢谢!如果您根本不想返回参数,请参照第1、2条,谢谢!<br>4、如果以上三条均不能理解,请及时补充脑白金,谢谢!!
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部