如果抛弃掉一个存储过程中查询得到的结果集?

twodays 2004-08-18 03:47:10
是这样子的,我的一个存储过程,姑且叫做A
A中调用了存储过程B和存储过程C,如下所示:

exec B.....
exec C......

这个B呢,是个系统存储过程,但是它偏偏给我返回了一个空的结果集
nnd
可是我只是想要存储过程C得到的结果集呀。。。。


虽说在外面调用这个A的外部程序中可以获得这两个结果集,然后只来使用那个我想要的C的结果集。。。
但是。。。。太麻烦了。。。。总觉得别扭。。。。

有啥子好办法。。。。在我这个A里面就把B的空结果集干掉吗?
...全文
354 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
prcgolf 2004-09-15
  • 打赏
  • 举报
回复
或:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_splitpage]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_splitpage]
GO

/*--利用SQL未公开的存储过程实现分页

方法简单且效率高,已知的问题就是要多返回一个空的记录集

解决的方法是在前台调用时,用 set recordset=recordset.nextrecordset
的方法跳过第一个记录集

此方法由J9988提供,我只是将它改成了方便调用的存储过程

--邹建 2004.05--*/
create procedure p_splitpage
@sql nvarchar(4000), --要执行的sql语句
@currentpage int=2, --要显示的页码
@pagesize int=10, --每页的大小
@pagecount int=0 out --总页数
as
set nocount on
declare @p1 int
declare @newsql varchar(2000)
set @newsql='
select * into ## from OPENROWSET(
''SQLOLEDB'',
''SERVER=server;uid=sa;pwd=;Database=master'',''SET FMTONLY OFF;set nocount on;exec sp_executesql N'''''+@sql +''''''') as a'
exec (@newsql)

insert into ## exec sp_cursoropen @p1 output,@sql,@scrollopt=1,@ccopt=1,@rowcount=@pagecount output

drop table ##

select @pagecount=ceiling(1.0*@pagecount/@pagesize)
,@currentpage=(@currentpage-1)*@pagesize+1
--select @currentpage
exec sp_cursorfetch @p1,16,@currentpage,@pagesize
exec sp_cursorclose @p1
go

--调用示例
exec p_splitpage 'SELECT * FROM sysobjects',2
prcgolf 2004-09-14
  • 打赏
  • 举报
回复

use master
go
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_get]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_get]
go
create procedure p_get
@sql nvarchar(4000) --要执行的sql语句
as
exec(@sql)
go
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_splitpage]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_splitpage]
GO

/*--利用SQL未公开的存储过程实现分页

方法简单且效率高,已知的问题就是要多返回一个空的记录集

解决的方法是在前台调用时,用 set recordset=recordset.nextrecordset
的方法跳过第一个记录集

此方法由J9988提供,我只是将它改成了方便调用的存储过程

--邹建 2004.05--*/
create procedure p_splitpage
@sql nvarchar(4000), --要执行的sql语句
@currentpage int=2, --要显示的页码
@pagesize int=10, --每页的大小
@pagecount int=0 out --总页数
as
set nocount on
declare @p1 int
declare @newsql varchar(2000)
set @newsql='
select * into ## from OPENROWSET(
''SQLOLEDB'',
''SERVER=server;uid=sa;pwd=;Database=master'',''SET FMTONLY OFF;set nocount on;exec p_get '''''+@sql +''''''') as a'
exec (@newsql)

insert into ## exec sp_cursoropen @p1 output,@sql,@scrollopt=1,@ccopt=1,@rowcount=@pagecount output

drop table ##

select @pagecount=ceiling(1.0*@pagecount/@pagesize)
,@currentpage=(@currentpage-1)*@pagesize+1
--select @currentpage
exec sp_cursorfetch @p1,16,@currentpage,@pagesize
exec sp_cursorclose @p1
go

--调用示例
exec p_splitpage 'SELECT * FROM sysobjects',2

twodays 2004-09-06
  • 打赏
  • 举报
回复
to zjcxc(邹建),chengte(成其一):
用临时表或者那种 not in之类的方法
我对他们的效率表示怀疑
而我这种方法是直接利用SQLServer在打开记录集的同时,就将光标定位到指定的位置
从理论上来说,速度应该比较好

to pbsql(风云):
B的返回结果集不固定,他会根据SQL语句的情况来返回和这个SQL语句的结果集同构的一个空记录集

to yizia(椅子):
我知道在外面可以处理,但是我想知道有没有办法直接把这个问题在SQL Server内部消化掉,用不着把这种东西放到外面的业务逻辑里面
chengte 2004-09-01
  • 打赏
  • 举报
回复
实现分页:
如果表中有主键(记录不重复的字段也可以),可以用类似下面的方法,当然y,(x-1)*y要换成具体的数字,不能用变量:

select top y * from 表 where 主键 not in(select top (x-1)*y 主键 from 表)



如果表中无主键,可以用临时表,加标识字段解决.这里的x,y可以用变量.

select id=identity(int,1,1),* into #tb from 表
select * from #tb where id between (x-1)*y and x*y-1
椅子 2004-09-01
  • 打赏
  • 举报
回复
如果是ado,可以用NextRecordset()来取得需要的结果集
zjcxc 2004-09-01
  • 打赏
  • 举报
回复
--给你参考一下我写的,也许能给你解决问题提供帮助.

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_show]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_show]
GO

/*--用存储过程实现的分页程序

显示指定查询结果的第X页
此存储过程针对无主键的情况,使用临时表的方法
如果有主键,不推荐此方法

--邹建 2003.09(引用请保留此信息)--*/

/*--调用示例
exec p_show 'select * from xzkh_new..地区资料'

exec p_show 'select * from xzkh_new..地区资料',5,2,'地区编号,地区名称,助记码','地区编号'
--*/
CREATE Proc p_show
@QueryStr nvarchar(1000), --查询语句,如果查询表,用:select * from 表
@PageSize int=10, --每页的大小(行数)
@PageCurrent int=1, --要显示的页
@FdShow nvarchar (1000)='', --要显示的字段列表,如果查询结果不需要标识字段,需要指定此值,且不包含标识字段
@FdOrder nvarchar (1000)='' --排序字段列表
as
declare @FdName nvarchar(50) --标识列名
,@Id1 varchar(20),@Id2 varchar(20) --开始和结束的记录号
select @FdName='[ID_'+cast(newid() as varchar(40))+']'
,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(20))
,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(20))
,@FdShow=case isnull(@FdShow,'') when '' then '*' else @FdShow end
,@FdOrder=case isnull(@FdOrder,'') when '' then '' else ' order by '+@FdOrder end

exec('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
into #tb from('+@QueryStr+') a '+@FdOrder+'
select '+@FdShow+' from #tb where '+@FdName+' between '
+@Id1+' and '+@Id2
)
GO

zjcxc 2004-09-01
  • 打赏
  • 举报
回复
既然是分页的,为什么又存在一个要抛掉查询结果集的问题呢?
pbsql 2004-09-01
  • 打赏
  • 举报
回复
你不是说B是个系统存储过程吗?难道它的返回集也不固定?
twodays 2004-09-01
  • 打赏
  • 举报
回复
可是在里面用临时表的话,那么就需要构造这个临时表,需要知道表的结构
其实你们看我的代码
我都说了,这个是用来做分页处理的
用它的好处就不是不需要去按照那些表的结构去分别的构造那些临时表
如果这里还要构造临时表的话,那么又回到一开始了。。。。
了缘 2004-08-26
  • 打赏
  • 举报
回复
up
netcoder 2004-08-26
  • 打赏
  • 举报
回复
用临时表保存结果集,是个办法:)
pbsql 2004-08-26
  • 打赏
  • 举报
回复
上面已经帖过了,将B的返回结果放到临时表中就不会显示了:
create table #t(re varchar(8000)) ---这个表结构与系统存储过程B的返回记录集相同
insert #t exec B.....
exec C......
frankyshu 2004-08-26
  • 打赏
  • 举报
回复
关注,我也遇到了一样的问题,不知道怎么解决
twodays 2004-08-23
  • 打赏
  • 举报
回复
是这样子的,我实际上是在利用一个SQL Server未公开的存储过程来做分页,这个方法忘了以前从哪里看到的,代码如下:

ALTER PROCEDURE SPLITPAGE
(
@SQL NVARCHAR(4000), --要执行的SQL语句
@CURRENTPAGE INT , --要显示的页码
@PAGESIZE INT , --每页的大小
@PAGECOUNT INT OUT --总页数
)
AS
SET NOCOUNT ON
DECLARE @P1 INT

EXEC SP_CURSOROPEN @P1 OUTPUT,@SQL,@SCROLLOPT = 1,@CCOPT = 1,@ROWCOUNT = @PAGECOUNT OUTPUT
--他就是在执行SP_CURSOROPEN的时候,输出了一个和查询语句同构的一个空的记录集
--通过set nocount on只能是使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息,并不能取消掉这个记录集

SET @PAGECOUNT = CEILING(1.0 * @PAGECOUNT / @PAGESIZE)
SET @CURRENTPAGE = (@CURRENTPAGE-1) * @PAGESIZE + 1
EXEC SP_CURSORFETCH @P1,16,@CURRENTPAGE,@PAGESIZE
EXEC SP_CURSORCLOSE @P1



btw:其实分页的存储过程也有别的方法,例如建立一个临时表什么的,我用这个方法,就是为了省事儿,不用在代码里面根据每个查询的情况去处理临时表
虽然通过外面的DataSet可以选择结果集,但是毕竟不太方便,感觉多了一个步骤。。。。
唉。。。。各位老大帮我看看应该怎么处理这个问题比较好?
qiliu 2004-08-18
  • 打赏
  • 举报
回复
sp_helptext 你调用的那个系统存储过程
:
看里面那一段是你想要的代码
了缘 2004-08-18
  • 打赏
  • 举报
回复
set nocount on

好象可以选择集合数据的,再看看
zjcxc 2004-08-18
  • 打赏
  • 举报
回复
--你试试这样处理

set nocount on
create table #t(re varchar(8000)) ---这个表结构与系统存储过程B的返回记录集相同
insert #t exec B.....
exec C......
zjcxc 2004-08-18
  • 打赏
  • 举报
回复
不知道你调用的是那个系统存储过程? 或许可以根据这个系统存储过程来做控制.
jackxing 2004-08-18
  • 打赏
  • 举报
回复
有的系统存储过程有可选参数 nooutput,看看b有没有

另外,如果存储过程返回多个结果集,可以在前端程序中处理
比如在.Net中,要是使用第二个结果集:

1、如果使用Dataview,可以这样使用 oDataset.Tables(1).DefaultView
2、如果使用OleDbDataReader,先运行 oReader.NextResult
twodays 2004-08-18
  • 打赏
  • 举报
回复
变通不了。。。。
B是个系统存储过程,必须先执行它,然后才能通过C取数据

我还真的没有找到什么可以变通的方法。。。。咳咳。。。。
加载更多回复(2)

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧