2012-09-26 39 views
7

Có cách nào để tạo một hàm CLR do người dùng định nghĩa cho SQL Server trả về nhiều giá trị mà không sử dụng cú pháp hàm giá trị bảng? Ví dụ: giả sử tôi muốn thực hiện chuyển đổi tọa độ, chẳng hạn như:SQL Server CLR UDF với tham số ngoài - Có thể thực hiện được không?

[SqlFunction()] 
public void ConvertCoordinates(SqlDouble x, SqlDouble y, SqlDouble z, out SqlDouble r, out SqlDouble t, out SqlDouble p) 
{ 
    r = new SqlDouble(Math.Sqrt((x.Value*x.Value)+(y.Value*y.Value)+(z.Value*z.Value))); 
    t = new SqlDouble(Math.Acos(r.Value/z.Value)); 
    p = new SqlDouble(Math.Atan(y.Value/x.Value)); 
} 

Điều này thậm chí còn có thể? Hàm bảng có giá trị trong trường hợp này có vẻ không phù hợp vì tính toán sẽ không bao giờ sinh ra nhiều hơn một hàng đầu ra. Sử dụng cú pháp hàm có giá trị vô hướng, tôi sẽ phải viết ba hàm khác nhau để thực hiện tính toán và gọi riêng từng hàm. Với trường hợp sử dụng thực tế của tôi, điều này là không thực tế.

Tôi nhận thấy rằng logic trên có thể được thực hiện bằng T-SQL thuần túy; trường hợp sử dụng thực tế của tôi phức tạp hơn nhưng vẫn chỉ dẫn đến một hàng có nhiều giá trị đầu ra phụ thuộc lẫn nhau.

Vì vậy, điểm mấu chốt, có khả thi không? Tôi không nghĩ đó là, nhưng người ta có thể hy vọng. Nếu tình cờ nó khả thi, thì T-SQL sẽ trông như thế nào khi gọi một hàm như vậy?

+1

UDF (cho dù Scalar, hoặc Tabular, T-SQL hoặc CLR) không thể có tham số. Nếu có thể, bạn phải tạo ra cú pháp mới để cho phép một cú pháp được gọi trong mệnh đề 'SELECT', nếu bạn muốn tiêu thụ các đầu ra này. Và tôi không thấy lý do tại sao một hàm có giá trị trả về một hàng nên có vẻ lạ đối với bạn. –

+1

@Damien Đây chỉ đơn giản là câu hỏi liệu có thể thực hiện được hay không.Đọc và thử nghiệm của riêng tôi đã chỉ ra rằng có lẽ không phải (như tôi cũng đã nói), nhưng vì tôi mới tham gia tích hợp CLR mà tôi muốn hỏi. TVFs không có vẻ "lạ với tôi" khi có nhiều hơn 1 hàng là một khả năng. Ví dụ ALWAYS trả về một hàng duy nhất, nhưng các giá trị trả lại tương quan chỉ có ý nghĩa như một tập hợp. Trong trường hợp sử dụng thực tế của tôi, tôi đang thực hiện một tính toán tương tự, nhưng lớn hơn cho hàng triệu hàng, vì vậy TVF dường như không hiệu quả nếu các tham số ngoài là một khả năng. Một 'không' đơn giản sẽ là đủ. – bporter

+0

@bporter - rõ ràng là TVF sẽ là lựa chọn tốt nhất - bạn tự nói, "không có vẻ lạ khi có hơn 1 hàng là một khả năng" và sau đó nói rằng bạn có hàng triệu hàng. Ergo a (S) TVF là câu trả lời! Nó sẽ trở nên hiệu quả hơn việc lặp lại trên mỗi hàng như một tuyên bố foreach bắt buộc. – gbjbaanb

Trả lời

3

Vì bạn đã lấy plunge CLR, bạn có thể tạo kiểu CLR của riêng bạn mà bạn có thể làm đủ thứ điên rồ. Như một ví dụ thực tế, các kiểu không gian gốc được thực hiện theo cách này, cũng như là HierarchyID. Khi bạn đã xác định loại của riêng mình, bạn có thể có chức năng trả về. Nếu nhận được các thành phần riêng lẻ (nếu tôi có thể giả định trong trường hợp bán kính của bạn, theta và phi), hãy tạo các phương thức trên kiểu trả về như vậy.

+0

Cảm ơn bạn đã đề xuất. Các UDT sẽ đơn giản hơn nhiều và tôi đã xem xét chúng. Mối quan tâm duy nhất tôi có là tôi phải đăng ký lắp ráp với mọi cơ sở dữ liệu. Trong trường hợp của tôi, tôi đang khai thác dữ liệu từ hàng trăm cơ sở dữ liệu được tích lũy trong 10 năm qua. Các UDF có vẻ đơn giản hơn vì tôi có thể đặt chúng trong một cơ sở dữ liệu và gọi chúng từ các cơ sở dữ liệu khác để thực hiện các phép tính. Có cách nào bạn biết để làm cho UDT có sẵn trên tất cả các cơ sở dữ liệu tương tự như các loại không gian (không đăng ký lắp ráp với mỗi cơ sở dữ liệu)? – bporter

+0

Tôi có thể nghĩ ra một vài cách tiếp cận. Đầu tiên là nếu bạn chỉ đăng ký nó một lần trong một db và thực hiện tất cả việc thu thập dữ liệu của bạn trong bối cảnh của db đó. Người kia sẽ triển khai nó ở mọi nơi. Vì đó là T-SQL và bạn có lẽ đã có cách để chạy mã với mọi db, đây không phải là vấn đề. Hãy nhớ rằng bạn có thể triển khai các assembly thông qua một quyền bitstream trong kịch bản thay vì phải triển khai DLL ở mọi nơi và tham chiếu đến nó. –

-1

Tôi thừa nhận tôi đã không thử nó, nhưng tôi tưởng tượng T-SQL muốn,

DECLARE @X FLOAT(53), 
     @Y FLOAT(53), 
     @Z FLOAT(53), 
     @R FLOAT(53), 
     @T FLOAT(53), 
     @P FLOAT(53) 

EXEC ConvertCoordinates 
     @X = 0, 
     @Y = 0, 
     @Z = 0, 
     @R = @R OUTPUT, 
     @T = @T OUTPUT 
     @P = @P OUTPUT 
1

Đây là câu hỏi cũ hơn và tôi đã tìm thấy câu hỏi đó trong khi tìm kiếm câu trả lời cho một câu hỏi rất giống nhau.

Hàm SQL cho phép trả về giá trị nhưng không cho phép sử dụng thông số đầu ra.

Thủ tục SQL làm phép các thông số đầu ra (nhưng không phải là một giá trị trả về)

Tôi thấy điều này từ MSDN Ví dụ ở đây:

http://technet.microsoft.com/en-us/library/ms131092.aspx

[Microsoft.SqlServer.Server.SqlProcedure] 
public static void PriceSum(out SqlInt32 value) 
{ … } 

CREATE PROCEDURE PriceSum (@sum int OUTPUT) 
AS EXTERNAL NAME TestStoredProc.StoredProcedures.PriceSum 

Khi tôi chuyển từ cố gắng đăng ký một chức năng cho một thủ tục ure tất cả mọi thứ đã làm việc ra. Cần phải chỉ ra rằng một hàm có thể có một giá trị trả về nhưng một thủ tục lưu trữ có thể không. Trong trường hợp của tôi, tôi đã trả về một giá trị chuỗi và có các tham số đầu ra cho một số thông tin chi tiết tùy chọn như mã trạng thái, v.v. Tất cả những gì tôi đã làm là thay đổi phương thức của mình thành void và chuyển giá trị chuỗi trở lại làm tham số đầu ra.

Phương pháp của bạn không có giá trị trả về và không có giá trị trả về và vì vậy là một ứng cử viên hoàn hảo để sử dụng Thủ tục được lưu trữ thay vì một hàm.

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