2011-07-07 42 views
19

Xem xét MẪU bảng:Duyệt qua hàng trong SQL Server 2008

id  integer 
name  nvarchar(10) 

Có một proc lưu trữ gọi là myproc. Nó chỉ mất một paramater (đó là id)

Với một tên như tham số, tìm tất cả các hàng với name = @nameparameter và vượt qua tất cả những id để myproc

ví dụ:

sample-> 
1 mark 
2 mark 
3 stu 
41 mark 

Khi mark là đã qua, 1 ,2 and 41 sẽ được chuyển đến myproc riêng lẻ.

ví dụ sau đây sẽ xảy ra:

execute myproc 1 
execute myproc 2 
execute myproc 41 

tôi không thể chạm vào myproc cũng không thấy nội dung của nó. Tôi chỉ phải truyền các giá trị cho nó.

+7

Mặc dù điều này * có thể được thực hiện, tốt nhất là tránh, thường là bằng cách chuyển đổi proc được lưu trữ thành UDF hoặc mở rộng nội tuyến để có thể thực hiện thao tác dựa trên thiết lập.Chúng tôi cần xem nội bộ của 'myproc' để tư vấn phương pháp nào khả thi trong trường hợp này. Trong SQL, bạn nên * thường * tìm kiếm các giải pháp dựa trên thiết lập cho các vấn đề, không phải các giải pháp dựa trên vòng lặp. –

+0

Simialr Câu hỏi được trả lời tại đây http://stackoverflow.com/questions/20662356/sql-server-loop-how-do-i-loop-through-a-set-of-records/34797745#34797745 – Sandeep

+1

@Sandeep, đây là một câu hỏi cũ hơn và tôi đã chấp nhận giải pháp – psy

Trả lời

42

Nếu bạn phải lặp (*), sử dụng các cấu trúc được thiết kế để làm điều đó - những cursor. Nhiều maligned, nhưng nếu nó thể hiện rõ nhất ý định của bạn, tôi nói sử dụng nó:

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 

(*) Câu trả lời này đã nhận được một vài upvotes thời gian gần đây, nhưng tôi cảm thấy tôi phải kết hợp bình luận ban đầu của tôi ở đây và thêm một số lời khuyên chung:

Trong SQL, bạn nên thường là tìm giải pháp dựa trên tập hợp. Toàn bộ ngôn ngữ được định hướng xung quanh các giải pháp dựa trên thiết lập, và (đến lượt nó) trình tối ưu hóa được định hướng xung quanh làm cho các giải pháp dựa trên thiết lập hoạt động tốt. Ngoài ra, các công cụ chúng tôi có sẵn để điều chỉnh trình tối ưu hóa cũng được đặt theo định hướng - ví dụ: áp dụng các chỉ mục cho các bảng.

vài tình huống trong đó lặp lại là cách tiếp cận tốt nhất. Đây là một số ít là xa giữa, và có thể được so sánh với các quy tắc của Jackson về tối ưu hóa - không làm điều đó - và (chỉ dành cho các chuyên gia) không làm điều đó chưa.

Bạn đang phục vụ tốt hơn trước tiên để xây dựng những gì bạn muốn về tập hợp tất cả các hàng bị ảnh hưởng - thay đổi tổng thể sẽ đạt được là gì? - và sau đó cố gắng xây dựng một truy vấn đóng gói mục tiêu đó. Chỉ khi truy vấn được tạo ra bằng cách thực hiện như vậy không hoạt động đầy đủ (hoặc có một số thành phần khác không thể làm bất cứ điều gì khác ngoài thỏa thuận với từng hàng riêng lẻ), bạn nên xem xét lặp lại.

+0

Tôi muốn sử dụng một con trỏ để gửi ra dbmail cho người nhận, được xác định bởi một truy vấn thiết lập, mỗi lần một để tôi có thể bắt lỗi. Theo phần thứ hai của câu trả lời của bạn, đây có phải là cách sử dụng phù hợp không? – DFTR

+1

@DFTR - nó có thể - miễn là bạn nhớ rằng bạn sẽ không thể bắt tất cả các lỗi có thể xảy ra ở giai đoạn này - việc gửi email không được đảm bảo ngay cả khi mọi thứ hoạt động tốt ở phía máy chủ SQL. –

+0

Vâng, tôi đã nghĩ về điều đó. Nhưng ít nhất tôi sẽ biết nó đã làm cho nó đến sophos của chúng tôi, đó là cơ bản mà công việc của tôi kết thúc. Vì vậy ... thắng. – DFTR

-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 ,'') 
6

Tôi chỉ cần khai báo @sample bảng tạm thời và chèn tất cả các hàng có tên = 'Rahul' và cũng có thể lấy cột trạng thái để kiểm tra xem hàng được iterated.and sử dụng trong khi vòng lặp i lặp qua tất cả các hàng của @sample bảng tạm thời mà có tất cả các id của name = 'Rahul'

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 [email protected] 
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 
+0

Bạn có thể khai báo ID là Identity (1.1) và lặp lại nó mà không cần phải cập nhật nó. –