存储过程中怎么处理结果集?

chy3503319 2007-11-15 01:41:31
想实现的效果
在存储过程中取出一个结果集
然后再分别取出每行进行处理

在程序中可以循环实现
datatable dt;

for(int i=0;i<=1;i++)
{
dt.row[i]........
}
在存储过程中怎么实现?
...全文
484 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
chy3503319 2007-11-15
  • 打赏
  • 举报
回复
结贴 谢谢大家
symbol441 2007-11-15
  • 打赏
  • 举报
回复
这句话的意思是取出单个行只能转移到变量中用,象程序中dt.row[i]........ 这样用是没有的吧
---------------------------------
嗯 ,是的
jzywh 2007-11-15
  • 打赏
  • 举报
回复
CURSOR
fcuandy 2007-11-15
  • 打赏
  • 举报
回复
方法很多.
1,游标,上面有人写了示例了,不再累赘.
2,含identity列的表变量
declare @t table(id int identity(1,1),v)
declare @k int,@i,int
insert @t select v from tb
select @i=0, @k=count(*) from @t
while @i<@i
begin
set @i=@i+1
select * from @t where id=@i
--do something
end
表变量的问题在于,存储过程返回的行集的结构要可预知,否则不能构建同结构的表变量
3,生成含identity列的临时表
select identity(int) id,v into # from tb
declare @k int,@i,int
select @i=0, @k=count(*) from #
while @i<@i
begin
set @i=@i+1
select * from # where id=@i
--do something
end
局部临时表解决了表变量需要预知行集结构的问题.
另外有个问题,如果要对行集中的所有列进行操作,而行集的列中可能本身已含有identity列
那么 无论使用临时表,不要将行集中的identity 列用 select into 的方式插入
在select into 方式复制数据的同时,也复制了结构,一个表中只能有一个identity列.
那么可以采用先建临时表,再用insert select方式来复制数据. 这就又跟表变量一样了.
而又要求操作原行集中的identity列,又不能预知行集的结构(不能预知结构就不能事先声明表变量或临时表)时,请采用下面方法
4,利用count计数法
declare @k int,@i,int
select @i=0, @k=count(*) from tb
while @i<@k
begin
set @i=@i+1
select * from tb a where @i=(select count(*) from tb where id<a.id) --从tb中查询第@i行
end


第4种方法比较费资源,不推荐.

以上的所有写法中, tb不一定就是表,可以指代你本身存储过程中产生行集的查询语句.

chy3503319 2007-11-15
  • 打赏
  • 举报
回复
谢谢大家 明白了
再问一下
使用 FETCH INTO 语句提取单个行,并把每列中的数据转移到指定的变量中。然后,其它 Transact-SQL 语句可以引用这些变量来访问已提取的数据值。Transact-SQL 不支持提取行块。

这句话的意思是取出单个行只能转移到变量中用,象程序中dt.row[i]........ 这样用是没有的吧
xh831213 2007-11-15
  • 打赏
  • 举报
回复
1 使用游标 ,这点楼上各位已经介绍不少了
2 使用函数 ,在数据库中建立一个函数来处理每条数据
LutzMark 2007-11-15
  • 打赏
  • 举报
回复
USE pubs
GO

-- Declare the variables to store the values returned by FETCH.
DECLARE @au_lname varchar(40), @au_fname varchar(20)


DECLARE authors_cursor CURSOR FOR
SELECT au_lname, au_fname FROM authors

ORDER BY au_lname, au_fname

OPEN authors_cursor

-- Perform the first fetch and store the values in variables.
-- Note: The variables are in the same order as the columns
-- in the SELECT statement.

FETCH NEXT FROM authors_cursor
INTO @au_lname, @au_fname

-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN

-- Concatenate and display the current values in the variables.
PRINT 'Author: ' + @au_fname + ' ' + @au_lname

-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM authors_cursor
INTO @au_lname, @au_fname
END

CLOSE authors_cursor
DEALLOCATE authors_cursor
GO


这个例子很好
我不懂电脑 2007-11-15
  • 打赏
  • 举报
回复
Transact-SQL 游标


Transact-SQL 游标主要用在存储过程、触发器和 Transact-SQL 脚本中,它们使结果集的内容对其它 Transact-SQL 语句同样可用。



在存储过程或触发器中使用 Transact-SQL 游标的典型进程为:




声明 Transact-SQL 变量包含游标返回的数据。为每一结果集列声明一个变量。声明足够大的变量以保存由列返回的值,并声明可从列数据类型以隐性方式转换得到的数据类型。



使用 DECLARE CURSOR 语句把 Transact-SQL 游标与一个 SELECT 语句相关联。DECLARE CURSOR 语句同时定义游标的特征,比如游标名称以及游标是否为只读或只进特性。



使用 OPEN 语句执行 SELECT 语句并生成游标。



使用 FETCH INTO 语句提取单个行,并把每列中的数据转移到指定的变量中。然后,其它 Transact-SQL 语句可以引用这些变量来访问已提取的数据值。Transact-SQL 不支持提取行块。



结束游标时,使用 CLOSE 语句。关闭游标可以释放某些资源,比如游标结果集和对当前行的锁定,但是如果重新发出一个 OPEN 语句,则该游标结构仍可用于处理。由于游标仍然存在,此时还不能重新使用游标的名称。DEALLOCATE 语句则完全释放分配给游标的资源,包括游标名称。在游标被释放后,必须使用 DECLARE 语句来重新生成游标。


监视 Transact-SQL 游标的活动


可以使用 sp_cursor_list 系统存储过程来获得对当前连接可见的游标列表,使用sp_describe_cursor、sp_describe_cursor_columns和 sp_describe_cursor_tables 来确定游标的特征。



在游标打开后,@@CURSOR_ROWS 函数或由 sp_cursor_list 或 sp_describe_cursor 返回的 cursor_rows 列会指出游标中的行数。



在每个 FETCH 语句执行之后,@@FETCH_STATUS 更新以反映最后一次提取的状态。也可以从由 sp_describe_cursor 返回的 fetch_status 列中获取该状态信息。@@FETCH_STATUS 报告游标中的状态,比如超出第一行和最后一行的提取。@@FETCH_STATUS 对于连接来说是全局性的,并在连接游标打开时由每次提取进行重置。如果必须在以后了解状态,就需要在连接中执行另外一个语句之前,把 @@FETCH_STATUS 保存在一个用户变量中。即使下一语句不是 FETCH,也可能是 INSERT、UPDATE 或 DELETE 这些语句,它们能够激发包含可重置 @@FETCH_STATUS 的 FETCH 语句的触发器。sp_describe_cursor 返回的 fetch_status 列对于指定的游标来说是确定的,不受那些引用其它游标的 FETCH 语句的影响,但 sp_describe_cursor 会受引用相同游标的 FETCH 语句的影响,因此使用时必须注意。



完成 FETCH 后,游标将定位在已提取的行上。被提取的行称为当前行。如果游标没有声明为只读游标,就可以执行带有 WHERE CURRENT OF cursor_name 子句的 UPDATE 或 DELETE 语句来修改当前行。



由 DECLARE CURSOR 语句赋给 Transact-SQL 游标的名称可以是全局或局部的。全局游标的名称可由任何位于同一连接上的批处理、存储过程或触发器引用。局部游标名称不能在声明游标的批处理、存储过程或触发器之外被引用。触发器和存储过程中的局部游标因而可以避免来自存储过程或触发器外部的无意引用。



使用游标变量


Microsoft® SQL Server™ 2000 也支持 cursor 数据类型的变量。游标可以有两种方法与一个 cursor 变量相关联:

/* Use DECLARE @local_variable, DECLARE CURSOR and SET. */DECLARE @MyVariable CURSORDECLARE MyCursor CURSOR FORSELECT LastName FROM Northwind.dbo.EmployeesSET @MyVariable = MyCursor/* Use DECLARE @local_variable and SET */DECLARE @MyVariable CURSORSET @MyVariable = CURSOR SCROLL KEYSET FORSELECT LastName FROM Northwind.dbo.Employees

当游标与 cursor 变量相关联之后,在 Transact-SQL 游标语句中就可以使用 cursor 变量代替游标名称。存储过程输出参数也可指派为 cursor 数据类型,并与一个游标相关联。这就允许存储过程有节制地展示其局部游标。



引用 Transact-SQL 游标


Transact-SQL 游标名称和变量只能由 Transact-SQL 语句引用,而不能由 OLE DB、ODBC、ADO 和 DB-Library 的 API 函数引用。例如,如果要使用 DECLARE CURSOR 和 OPEN 语句生成一个 Transact-SQL 游标,就无法使用 SQLFetch 或 SQLFetchScroll 函数来从 Transact-SQL 游标中提取行。需要游标处理而又使用这些 API 的应用程序应该使用数据库 API 中内建的游标支持代替 Transact-SQL 游标。



通过使用 FETCH 并绑定由 FETCH 返回给程序变量的每一列,可以在应用程序中使用 Transact-SQL 游标。Transact-SQL FETCH 不支持批处理,因此,这是将数据返回给应用程序的效率最低的方法。每提取一行均需往返服务器一次。使用内建在数据库 API 中的游标功能更为有效,可进行多行提取。



当包含在存储过程和触发器中时,Transact-SQL 游标极其有效。这是因为所有操作都编译到服务器上的一个执行计划内,不存在与行提取有关的网络流量。
symbol441 2007-11-15
  • 打赏
  • 举报
回复
LZ参考下采用游标,把记录值写入变量
其原理就是hbxtlhx 所说


USE pubs
GO

-- Declare the variables to store the values returned by FETCH.
DECLARE @au_lname varchar(40), @au_fname varchar(20)


DECLARE authors_cursor CURSOR FOR
SELECT au_lname, au_fname FROM authors

ORDER BY au_lname, au_fname

OPEN authors_cursor

-- Perform the first fetch and store the values in variables.
-- Note: The variables are in the same order as the columns
-- in the SELECT statement.

FETCH NEXT FROM authors_cursor
INTO @au_lname, @au_fname

-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN

-- Concatenate and display the current values in the variables.
PRINT 'Author: ' + @au_fname + ' ' + @au_lname

-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM authors_cursor
INTO @au_lname, @au_fname
END

CLOSE authors_cursor
DEALLOCATE authors_cursor
GO

seedling_lq 2007-11-15
  • 打赏
  • 举报
回复
在存储过程里结果集可以看成临时表,至于循环那也就相当与遍历游标,具体处理和在程序里没什么不同
北京的雾霾天 2007-11-15
  • 打赏
  • 举报
回复
下面的示例打开一个游标并且提取所有的行。

DECLARE Employee_Cursor CURSOR FOR
SELECT LastName, FirstName
FROM Northwind.dbo.Employees
WHERE LastName like 'B%'

OPEN Employee_Cursor

FETCH NEXT FROM Employee_Cursor
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM Employee_Cursor
END

CLOSE Employee_Cursor
DEALLOCATE Employee_Cursor

北京的雾霾天 2007-11-15
  • 打赏
  • 举报
回复
可以使用游标处理

62,039

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

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