迭代SQL Server 2008中的行

时间:2011-07-07 06:29:51

标签: sql sql-server-2008

考虑表SAMPLE:

id       integer
name     nvarchar(10)

有一个名为myproc的存储过程。它只需要一个参数(即id)

给定一个名称作为参数,找到name = @nameparameter的所有行并传递所有这些ID 到myproc

例如:

sample->
1   mark
2   mark
3   stu
41  mark

通过mark后,1 ,2 and 41将分别传递给myproc

即。应该发生以下情况:

execute myproc 1
execute myproc 2
execute myproc 41

我无法触及myproc,也无法查看其内容。我只需将值传递给它。

3 个答案:

答案 0 :(得分:42)

如果必须迭代(*),请使用旨在执行此操作的构造 - cursor。非常诽谤,但如果它最清楚地表达了你的意图,我说要用它:

DECLARE @ID int
DECLARE IDs CURSOR LOCAL FOR select ID from SAMPLE where Name = @NameParameter

OPEN IDs
FETCH NEXT FROM IDs into @ID
WHILE @@FETCH_STATUS = 0
BEGIN
    exec myproc @ID

    FETCH NEXT FROM IDs into @ID
END

CLOSE IDs
DEALLOCATE IDs

(*)这个答案最近收到了一些赞成,但我觉得我也应该在这里加入我的原始评论,并添加一些一般性建议:

在SQL中,您应该通常寻找基于集合的解决方案。整个语言都围绕基于集合的解决方案,而(反过来)优化器的目标是使基于集合的解决方案运行良好。进一步说,我们可用于调整优化器的工具也是面向集合的 - 例如,将索引应用于表。

有一些很少的情况,其中迭代是最好的方法。这些是很少的,可以比作杰克逊的优化规则 - 不要这样做 - 并且(仅限专家)不要

首先尝试根据受影响的所有行的集合来制定您想要的东西,你会得到更好的服务 - 要实现的整体变化是什么? - 然后尝试制定封装该目标的查询。只有当这样做产生的查询没有充分执行时(或者除了单独处理每一行之外还有其他一些组件无法做任何事情),你应该考虑迭代。

答案 1 :(得分:6)

我只是声明临时表@sample并插入所有具有name ='rahul'的行,并且还使用status列来检查该行是否已迭代。并使用while循环迭代所有临时行table @sample,其中包含name ='rahul'的所有ID

use dumme

Declare @Name nvarchar(50)
set @Name='Rahul'
DECLARE @sample table (

    ID int,
    Status varchar(500)

    )
insert into @sample (ID,status) select ID,0 from sample where sample=@name
while ((select count(Id) from @sample where status=0 )>0) 
begin
    select top 1  Id  from @sample where status=0 order by Id
    update @sample set status=1  where Id=(select top 1  Id  from @sample where status=0 order by Id) 
end

答案 2 :(得分:-3)

Declare @retStr varchar(100)

select @retStr = COALESCE(@retStr, '') + sample.ID + ', '
from sample 
WHERE sample.Name = @nameparameter 
select  @retStr = ltrim(rtrim(substring(@retStr , 1, len(@retStr )- 1)))

Return  ISNULL(@retStr ,'')