ADOStoredProc调用一个返回多个结果集的存储过程,存储过程代码大概是这样:
select * from
insert into
select * from
select * from
然后使用如下的Delphi代码
ADOQuery1.RecordSet = ADOStoredProc.RecordSet;
ADOQuery2.RecordSet = ADOStoredProc.NextRecordset(i);
ADOQuery3.RecordSet = ADOStoredProc.NextRecordset(i);
把多个RecordSet赋值给不同的ADOQuery并显示到界面上。
ADOQuery2.RecordSet = ADOStoredProc.NextRecordset(i);出现了RecordSet is not open,这让我非常不解,因为在SQLServer2005中调用这个存储过程没有任何问题,但执行程序就出现这个错误提示。
上网搜索到的结果基本上无解,只有:http://hi.baidu.com/opscontrol/blog/item/d13d87ea5bfd0adad539c9a1.html 这个网友说明了:因为存储过程中的语句有插入操作,返回的数据集中包括了影响行数的设置。在存储过程的头部写上这句:set nocount on 问题即可解决
我的理解是不使用set nocount on,ADOStoredProc实际返回的结果集为:
select * from
insert into result @@RowCount
select * from
select * from
也就是返回了4个结果集,而不是我希望的3个。这就是造成了RecordSet is not open的原因。也是写上set nocount on后忽略insert into result @@RowCount问题也就随之解决。
本来问题到这里也就解决了。但我发现写上set nocount on在头部,在SQLServer2005的Management studio中执行存储过程时同样不再提示记录集接受影响的行数,这带来了部份不便,且如果调整SQL语句的顺序为:
insert into
select * from
select * from
select * from
1、调整SQL代码的顺序,保证返回多个数据集的select中没有插入其它的insert, update, delete语句
2、如果不能调整SQL语句的顺序,那么在多个select间的insert, update, delete语句使用set nocount on和set nocount off以保证SQL的返回结果。如上例如不能调整顺序,正确的SQL写法为:
select * from
set nocount on
insert into
set nocount off
select * from
select * from
3、如果不能调整SQL语句的顺序,又想知道所有受影响的记录数量(在SQLServer2005的Management studio执行存储过程时),那么可以调整Delphi的代码,如本例调整Delphi的赋值代码为:
ADOQuery1.RecordSet = ADOStoredProc.RecordSet;
ADOStoredProc.NextRecordset(i); //对应SP中的Insert into 并忽略返回的受影响行数
ADOQuery2.RecordSet = ADOStoredProc.NextRecordset(i);
ADOQuery3.RecordSet = ADOStoredProc.NextRecordset(i);
最后:ADOStoredProc.NextRecordset(i);的参数i表示这个recordset中有多少行记录。