2010-01-05 22 views
21

Tại sao SQL Server không hỗ trợ các khối TRY-CATCH bên trong UDF?Tại sao khối TRY-CATCH không được phép bên trong UDF?

Nếu chúng ta đang nói về UDF vô hướng, chủ yếu được sử dụng để tính toán và hội thoại, khối này nên được sử dụng nhiều, nhưng chúng tôi không có nó.

Ngoài ra, bạn sử dụng giải pháp nào cho việc này?

+3

+1 câu hỏi hay – kevchadders

Trả lời

12

UDF trong MSSQL không được phép có các tác dụng phụ, mà BOL định nghĩa là "thay đổi trạng thái cơ sở dữ liệu". Đó là một mô tả khá mơ hồ, nhưng MSSQL rõ ràng xem xét lỗi để thay đổi trạng thái cơ sở dữ liệu - UDF này không biên dịch:

create function dbo.foo() 
returns int 
as 
begin 
    raiserror('Foo', 16, 1) 
    return 1 
end 
go 

Các thông báo lỗi là:

Msg 443, Level 16, State 14 , Quy trình foo, Dòng 5 Sử dụng không hợp lệ một nhà điều hành tác động phụ 'RAISERROR' trong một hàm.

Nếu việc tăng lỗi được xem là thay đổi trạng thái cơ sở dữ liệu, sau đó bẫy và xử lý một biến có lẽ là quá. Đó không phải là một lời giải thích, tôi thừa nhận.

Tuy nhiên, trong điều kiện thực tế, tốt nhất là hãy để người gọi quyết định cách xử lý lỗi. Giả sử bạn viết một hàm như thế này:

create function dbo.divide (@x int, @y int) 
returns float 
as 
begin 
return @x/cast(@y as float) 
end 

Làm thế nào bạn sẽ xử lý các trường hợp một ứng dụng đi không cho @y? Nếu bạn bắt được phân chia bằng không ngoại lệ, bạn sẽ làm gì tiếp theo? Giá trị nào bạn có thể trả về từ hàm có ý nghĩa với người gọi, nhớ rằng bạn thậm chí có thể không biết ứng dụng nào đang gọi hàm của bạn?

Bạn có thể nghĩ đến việc trả về NULL, nhưng các nhà phát triển ứng dụng có sử dụng chức năng của bạn đồng ý không? Tất cả các ứng dụng của họ có cân nhắc sai số bằng 0 để có cùng tác động hoặc tầm quan trọng không? Chưa kể rằng NULL ở những nơi nhất định hoàn toàn có thể thay đổi kết quả của một truy vấn, có lẽ theo cách mà nhà phát triển ứng dụng không muốn chút nào.

Nếu bạn là nhà phát triển duy nhất, có thể đó không phải là vấn đề, nhưng với nhiều người, nó nhanh chóng trở thành một.

+1

Tôi muốn tái tạo hành vi của TRY_CAST bằng cách viết UDF của riêng mình: –

1

Là một công việc xung quanh, tôi sẽ gọi UDF từ TRY/CATCH bên trong một thủ tục được lưu trữ.

+2

Cảm ơn bạn đã trả lời, nhưng khi bạn viết một UDF, nó thường được người khác sử dụng lại. Giải pháp của bạn hoạt động nếu tôi viết cả hai chức năng và người gọi, nhưng bạn không bao giờ có thể chắc chắn người khác sẽ gọi thủ tục của bạn đúng cách. –

+0

đúng ... tôi nghĩ rằng ck đã làm một điểm tốt về tiềm năng của nó được gọi là hàng ngàn lần, do đó, chi phí của một thử/bắt có thể là rất lớn. – kevchadders

1

Có thể vì chi phí quá cao - chức năng vô hướng có thể được gọi trên cột như một phần của một lựa chọn và được gọi là hàng nghìn lần. Nếu có một chi phí hợp lý để cho phép thử/bắt nó sẽ làm chậm nó xuống một cách khủng khiếp.

+0

+1 điểm tốt về tổng chi phí – kevchadders

+3

Có, ck, nhưng chúng tôi có thể nói tương tự cho nhiều khía cạnh khác của lập trình (con trỏ đến tâm trí). Tôi có thể nói rằng nhà phát triển viết chức năng này để quyết định xem việc triển khai và sử dụng có thể sẽ là chi phí và mã tương ứng hay không. –

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