2008-09-12 31 views
36

Tôi đang sử dụng SQL Server 2005 và tôi muốn biết cách truy cập các tập kết quả khác nhau từ trong giao dịch-sql. Thủ tục được lưu sau đây trả về hai bộ kết quả, làm cách nào để truy cập chúng, ví dụ, một thủ tục lưu sẵn khác?Truy cập vào tập kết quả từ trong các thủ tục được lưu trữ Transact-SQL SQL Server

CREATE PROCEDURE getOrder (@orderId as numeric) AS 
BEGIN 
    select order_address, order_number from order_table where order_id = @orderId 
    select item, number_of_items, cost from order_line where order_id = @orderId 
END 

Tôi cần có khả năng lặp lại thông qua cả hai bộ kết quả riêng lẻ.

EDIT: Chỉ cần làm rõ câu hỏi, tôi muốn kiểm tra các thủ tục được lưu trữ. Tôi có một tập hợp các thủ tục lưu trữ được sử dụng từ một khách hàng VB.NET, trả về nhiều tập kết quả. Những điều này sẽ không được thay đổi thành một hàm có giá trị bảng, tôi không thể thay đổi các thủ tục. Thay đổi thủ tục không phải là một lựa chọn.

Bộ kết quả được trả về theo quy trình không phải là cùng loại dữ liệu hoặc số cột.

Trả lời

34

Câu trả lời ngắn gọn là: bạn không thể làm điều đó.

Từ T-SQL không có cách nào để truy cập nhiều kết quả của cuộc gọi thủ tục được lưu trữ lồng nhau, mà không thay đổi thủ tục được lưu trữ như những người khác đã đề xuất.

Để được hoàn tất, nếu các thủ tục đã được trả lại một kết quả duy nhất, bạn có thể chèn nó vào một bảng temp hoặc biến bảng với cú pháp sau:

INSERT INTO #Table (...columns...) 
EXEC MySproc ...parameters... 

Bạn có thể sử dụng cú pháp tương tự cho một thủ tục mà trả về nhiều kết quả, nhưng nó sẽ chỉ xử lý kết quả đầu tiên, phần còn lại sẽ bị loại bỏ.

+2

Tôi vừa thử nghiệm giải pháp của Brannon, và trên thực tế, nếu tất cả các truy vấn trong thủ tục được lưu trữ gọi là trả về cùng số cột và kiểu dữ liệu, tập hợp kết quả trả về sẽ bao gồm một tổ hợp các tập kết quả. Đó là khá nhiều vô dụng. Cảm ơn sự giúp đỡ của bạn. –

0

Bạn có thể chọn chúng thành các bảng tạm thời hoặc viết các hàm có giá trị để trả về các tập kết quả. Đang hỏi cách lặp qua các tập kết quả?

1

Có hai cách để thực hiện việc này một cách dễ dàng. Hoặc là kết quả trong một bảng tạm thời và sau đó tham khảo bảng tạm thời từ sproc của bạn. Một lựa chọn khác là đưa các kết quả vào một biến XML được sử dụng như một biến OUTPUT.

Tuy nhiên, có ưu và khuyết điểm đối với cả hai tùy chọn này. Với một bảng tạm thời, bạn sẽ cần phải thêm mã vào kịch bản lệnh tạo thủ tục gọi để tạo bảng tạm thời trước khi sửa đổi thủ tục. Ngoài ra, bạn nên làm sạch bảng tạm thời ở cuối thủ tục.

Với XML, nó có thể là bộ nhớ chuyên sâu và chậm.

4

Lưu ý rằng có giới hạn phụ, không có giấy tờ đối với câu lệnh INSERT INTO ... EXEC: nó không thể lồng nhau. Đó là, các proc được lưu trữ mà các cuộc gọi EXEC (hoặc bất kỳ mà nó gọi lần lượt) không thể tự làm một INSERT INTO ... EXEC. Dường như có một miếng đệm trên mỗi quá trình tích lũy kết quả, và nếu chúng được lồng nhau, bạn sẽ gặp lỗi khi người gọi mở nó lên, và sau đó callee cố gắng mở lại.

Matthieu, bạn cần duy trì các bảng tạm thời riêng biệt cho từng "loại" kết quả. Ngoài ra, nếu bạn đang thực hiện cùng một lần nhiều lần, bạn có thể cần thêm cột bổ sung vào kết quả đó để cho biết kết quả của cuộc gọi đó.

2

Đáng buồn là không thể làm điều này. Vấn đề là, tất nhiên, không có Cú pháp SQL để cho phép nó. Nó xảy ra 'bên dưới mui xe' tất nhiên, nhưng bạn không thể có được những kết quả khác trong TSQL, chỉ từ các ứng dụng thông qua ODBC hoặc bất cứ điều gì.

Có một cách làm tròn nó, giống như hầu hết mọi thứ. Bí quyết là sử dụng tự động hóa ole trong TSQL để tạo một đối tượng ADODB mở mỗi resultset lần lượt và ghi kết quả vào các bảng mà bạn chỉ định (hoặc làm bất cứ điều gì bạn muốn với các kết quả). bạn cũng có thể làm điều đó trong DMO nếu bạn thích cơn đau.

8

Tôi đã có thể dễ dàng thực hiện điều này bằng cách tạo một thủ tục lưu sẵn SQL2005 CLR chứa bộ dữ liệu nội bộ.

Bạn thấy, một SqlDataAdapter mới sẽ .Fill một sproc nhiều kết quả thành một tập dữ liệu nhiều bảng theo mặc định. Dữ liệu trong các bảng này lần lượt có thể được chèn vào các bảng #Temp trong sproc gọi bạn muốn viết. dataset.ReadXmlSchema sẽ hiển thị cho bạn lược đồ của từng tập kết quả.

Bước 1: Bắt đầu viết sproc mà sẽ đọc dữ liệu từ sproc đa kết quả thiết lập

a. Tạo một bảng riêng cho mỗi tập kết quả theo lược đồ.

CREATE PROCEDURE [dbo].[usp_SF_Read] AS 
SET NOCOUNT ON; 
CREATE TABLE #Table01 (Document_ID VARCHAR(100) 
    , Document_status_definition_uid INT 
    , Document_status_Code VARCHAR(100) 
    , Attachment_count INT 
    , PRIMARY KEY (Document_ID)); 

b. Tại thời điểm này, bạn có thể cần phải khai báo một con trỏ đến nhiều lần gọi CLR sproc bạn sẽ tạo ra ở đây:

Bước 2: Hãy CLR SPROC

Partial Public Class StoredProcedures 
    <Microsoft.SqlServer.Server.SqlProcedure()> _ 
    Public Shared Sub usp_SF_ReadSFIntoTables() 

    End Sub 
End Class 

a. Kết nối bằng cách sử dụng New SqlConnection("context connection=true").

b. Thiết lập một đối tượng lệnh (cmd) để chứa sproc nhiều kết quả.

c. Nhận tất cả dữ liệu bằng cách sử dụng các mục sau:

Dim dataset As DataSet = New DataSet 
    With New SqlDataAdapter(cmd) 
     .Fill(dataset) ' get all the data. 
    End With 
'you can use dataset.ReadXmlSchema at this point... 

d. Lặp lại trên mỗi bảng và chèn mỗi hàng vào bảng tạm thời thích hợp (mà bạn đã tạo ở bước một ở trên).

Lưu ý cuối cùng: Theo kinh nghiệm của tôi, bạn có thể thực thi một số mối quan hệ giữa các bảng để biết từng bản ghi nào được tạo ra.

Đó là tất cả những gì đã xảy ra!

~ Shaun, Near Seattle

+0

Trong khi SQLCLR là cách duy nhất để thực sự giải quyết vấn đề này, việc dễ dàng chuyển sang 'DataSet' là _not_ có thể mở rộng vì tất cả các kết quả từ tất cả các tập kết quả sẽ nằm trong bộ nhớ. Phương thức thích hợp/có khả năng mở rộng hơn là lặp qua một 'SqlDataReader' và trả về mỗi hàng khi nó được đọc từ' SqlDataReader'. @ DanRadu của câu trả lời ở đây, bên ngoài không xử lý tất cả các kiểu dữ liệu (một sửa chữa ngắn sắp tới), gửi mỗi hàng như nó được đọc: http://stackoverflow.com/questions/6388489/insert-into-temp-table-from-a -stored-procedure-that-returns-nhiều kết quả-bộ/11045189 # 11045189 –

5

Có một số lượng lớn bạn có thể làm. Thêm tham số tùy chọn N int vào sproc của bạn. Mặc định giá trị của N đến -1. Nếu giá trị của N là -1, thì hãy thực hiện mọi lựa chọn của bạn. Nếu không, hãy chọn Nth và chỉ chọn Nth.

Ví dụ,

if (N = -1 or N = 0) 
    select ... 

if (N = -1 or N = 1) 
    select ... 

Những người gọi của sproc của bạn những người không chỉ định N sẽ nhận được một kết quả thiết lập với nhiều hơn một bảng. Nếu bạn cần trích xuất một hoặc nhiều bảng này từ một sproc khác, chỉ cần gọi sproc của bạn chỉ định một giá trị cho N. Bạn sẽ phải gọi sproc một lần cho mỗi bảng bạn muốn trích xuất. Không hiệu quả nếu bạn cần nhiều hơn một bảng từ tập kết quả, nhưng nó hoạt động trong TSQL tinh khiết.

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