【问题标题】:Iterate through rows in SQL Server 2008遍历 SQL Server 2008 中的行
【发布时间】:2011-07-07 06:29:51
【问题描述】:

考虑表 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,也无法查看其内容。我只需要将值传递给它。

【问题讨论】:

  • 虽然这个可以做到,但一般最好避免,通常是将存储的proc转换成UDF,或者内联扩展,这样就可以执行基于集合的操作.我们需要查看myproc 的内部结构,以告知在这种情况下哪种方法可行。在 SQL 中,您应该通常寻求基于集合的问题解决方案,而不是基于循环的解决方案。
  • 在这里回答了类似的问题stackoverflow.com/questions/20662356/…
  • @Sandeep,这是一个较老的问题,我已经接受了解决方案

标签: sql sql-server-2008


【解决方案1】:

如果您必须迭代(*),请使用专门设计的构造 - 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 中,您应该一般寻求基于集合的解决方案。整个语言都围绕基于集合的解决方案,并且(反过来)优化器旨在使基于集合的解决方案运行良好。进而,我们可用于调整优化器的工具也是面向集合的 - 例如将索引应用于表。

少数种情况下迭代是最好的方法。这些都是相距甚远的,并且可能类似于杰克逊的优化规则 - 不要这样做 - 并且(仅限专家)不要这样做

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

【讨论】:

  • 我想使用游标将 dbmail 发送给收件人,这些收件人由一组查询定义,一次一个,这样我就可以捕获故障。根据您回答的第二部分,这是否合适?
  • @DFTR - 它可能是 - 只要您记住在此阶段您将无法捕获所有可能的故障 - 即使一切正常,也不能保证电子邮件传递SQL Server 端。
  • 是的,我想到了。但至少我会知道它到达了我们的 sophos,这基本上是我的工作结束的地方。所以......赢了。
【解决方案2】:

我只是声明临时表@sample 并插入所有具有 name='rahul' 的行,并使用状态列检查该行是否已迭代。并使用 while 循环我遍历临时表的所有行具有 name='rahul' 的所有 id 的表 @sample

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

【讨论】:

  • 您可以将 ID 声明为 Identity(1,1) 并循环遍历它而无需更新它。
【解决方案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 ,'') 

【讨论】:

    猜你喜欢
    • 2010-12-16
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 2019-04-27
    相关资源
    最近更新 更多