2013-09-16 63 views
13

Có thể nào đó để thực hiện một số mã cho mỗi hàng của một lựa chọn mà không cần sử dụng con trỏ không?TSQL - thực hiện mã cho mỗi hàng của một lựa chọn

Trong trường hợp của tôi: Tôi đang có bảng tạm thời để lưu trữ một số dữ liệu cho tập lệnh phức tạp. Cuối cùng tôi muốn pint một số thông tin của bảng này (giới hạn bởi một số điều kiện) để đầu ra.

Hiện tại tôi đang sử dụng con trỏ có lựa chọn để giới hạn các hàng của bảng. Trong con trỏ này, tôi đang sử dụng

print '...' 

để tạo đầu ra.

Phải có một cách dễ dàng hơn để làm những việc như vậy ...

chỉnh sửa:

create table #tmpAttributes(AttributeId uniqueidentifier, Value float, ValueString nvarchar(max), ActionId uniqueidentifier) 

insert into #tmpAttributes (AttributeId, Value, ValueString, ActionId) 
    select ID,..... -- in this select i'm doing some value conversions, if conversion is not possible i'm using -1 

insert into ActionAttribute (ActionDefinitionID, Discriminator, ID, ReferredActionID, ValueDate, ValueListID, ValueMoney, ValueString, ValueUserID) 
    select @defId, 'ActionAttributeMoneyEntity', NEWID(), ActionId, null, null, Value, null, null from #tmpAttributes 

-- afterwards there is this cursor where I'm printint all rows where Value = -1 
+2

Không đủ thông tin.Bạn đang thực sự cố gắng đạt được điều gì? Nếu bạn cung cấp cho chúng tôi tình huống hoàn chỉnh, bạn có thể thấy rằng có một cách hoàn toàn dựa trên việc làm những gì bạn yêu cầu. – gvee

+0

Tại sao bạn không đặt thêm một cột nhận dạng trên 'bảng tạm thời' mà bạn đã tạo và lặp lại cho mỗi hàng. –

+0

Nếu bạn chỉ muốn in những thông tin "ở cuối" tại sao bạn cần một con trỏ sau đó? – DrCopyPaste

Trả lời

19

Thực thi lệnh in cho mỗi hàng trong tập hợp kết quả khá nhiều yêu cầu con trỏ hoặc cách tiếp cận tương tự như

này
declare @id int, @stuff varchar(20) 
declare @tmp table 
(
    id int not null 
, stuff varchar(20) 

    primary key(id) 
) 

insert @tmp 
select id, stuff from mastertable 
where condition1 > condition2 

select top 1 @id=id, @stuff=stuff from @tmp 

while (@@rowcount > 0) 
begin 
    print @stuff 
    delete from @tmp where [email protected] 
    select top 1 @id=id, @stuff=stuff from @tmp 
end 

Bạn vẫn đang lặp qua từng hàng, nhưng bạn tránh con trỏ. Vì bạn đang sử dụng một bảng var bạn thay vì một con trỏ, bạn tránh khóa bảng, nhưng điều này không nhất thiết phải là một cách tiếp cận tốt hơn. Bạn có thể xử lý từng hàng theo nhiều cách có thể khác nhau như thêm "cột đã xử lý" hoặc đánh số tất cả các hàng đã chọn 1..n và lặp lại dựa trên số rê chuột

Bạn chỉ có thể tránh xử lý theo hàng nếu bạn có thể thực hiện thao tác dựa trên tập hợp. Không có đủ thông tin trong câu hỏi của bạn để xem điều này có tránh được trong TSQL

Bây giờ, viết một CLR proc có thể linh hoạt hơn khi bạn có một mô hình lập trình phong phú hơn nhiều và có rất ít chi phí để lặp qua từng hàng tập hợp kết quả trong proc CLR. Thực hiện cuộc gọi cơ sở dữ liệu từ proc CLR cho mỗi hàng mà một cuộc gọi cơ sở dữ liệu từ mỗi hàng trong TSQL

EDIT - Tôi thấy ai đó đã thêm một cách có thể để chuyển đổi các câu lệnh in thành hoạt động định hướng. tức là

declare @msg varchar(max) 
select @msg = '' 

select msg = @msg + stuff 
from mastertable where condition1 > condition2 

print @msg 

Điều này là tốt, trên thực tế tối ưu những gì tôi đã đề cập đến khi tôi thực hiện một thao tác được đặt. Một hoạt động dựa trên bộ luôn được ưu tiên khi có thể. Nó có thể không được rõ ràng, nhưng chuỗi nối cũng có thể nhận được rất chậm trong ví dụ này quá nếu nhiều hàng có liên quan.


Tôi đã nói rằng sử dụng biến tạm thời tránh khóa bảng. Điều này là không chính xác đúng như máy chủ sql không viết temp temp vào một bảng trong tempdb. Điều tôi thực sự muốn nói là bạn tránh khóa bảng sản xuất và vì bạn được đảm bảo là người dùng duy nhất của bảng này, bạn không cạnh tranh để truy cập đồng thời.

Tôi cũng không cố gắng tối ưu hóa điều này. Ví dụ, vòng lặp bên trong có thể theo dõi id và điều kiện nơi trở thành nơi id> @id (bạn cũng sẽ muốn một khóa chính được xác định trên id). Kể từ khi bảng tạm thời không được cập nhật trong mỗi vòng lặp lặp đi lặp lại tôi mong đợi nó sẽ được nhanh hơn.

+0

Vẫn là một vòng lặp nhưng không sử dụng con trỏ "nặng". Cảm ơn bạn! –

8

Tôi nghĩ rằng bạn cần phải cung cấp chi tiết hơn, nhưng bạn có thể tìm kiếm một cái gì đó như:

declare @msg varchar(max)=''; 

select @msg = @msg + 'Output line: ' + ColumnA + ' -- ' + 'ColumnB' + char(13)+char(10) 
from #temp 
where ... 
; 

print @msg; 
+0

Vì vậy, đối với mỗi hàng giá trị của biến sẽ được mở rộng ... ý tưởng tốt đẹp! –

+0

Đảm bảo thêm 'TÙY CHỌN (MAXDOP 1)' để ngăn chặn song song, điều đó sẽ cho kết quả không mong muốn. – gjvdkamp

Các vấn đề liên quan