2011-10-14 63 views
10

Tôi tin rằng không có gì hiện có trong MySQL cho phép truy cập vào SQLSTATE của câu lệnh được thực thi cuối cùng trong một thủ tục lưu sẵn MySQL. Điều này có nghĩa là khi một SQLException chung được nâng lên trong một thủ tục lưu sẵn thì khó có thể lấy được bản chất của lỗi.Thủ tục lưu trữ MySQL Xử lý lỗi

Có ai có giải pháp cho việc phát sinh SQLSTATE của một lỗi trong một thủ tục lưu sẵn MySQL không liên quan đến việc khai báo một trình xử lý cho mọi SQLSTATE có thể không?

Ví dụ - hãy tưởng tượng rằng tôi đang cố gắng để trả lại một ERROR_STATUS mà đi vượt ra ngoài "SQLException xảy ra ở đâu đó trong BEGIN....END khối này" generic trong những điều sau đây:

DELIMITER $$ 

CREATE PROCEDURE `myProcedure`(OUT o_error_status varchar(50)) 
MY_BLOCK: BEGIN 

DECLARE EXIT handler for 1062 set o_error_status := "Duplicate entry in table"; 
DECLARE EXIT handler for 1048 set o_error_status := "Trying to populate a non-null column with null value"; 
-- declare handlers ad nauseum here.... 

DECLARE EXIT handler for sqlexception set o_error_status:= "Generic SQLException. You'll just have to figure out the SQLSTATE yourself...." ; 

-- Procedure logic that might error to follow here... 

END MY_BLOCK$$ 

Bất cứ lời khuyên?

PS Tôi đang chạy MySQL 5.1.49

Trả lời

8

Tôi tin rằng không có gì hiện đang có sẵn trong MySQL cho phép truy cập vào các SQLSTATE của báo cáo kết quả thực hiện cuối cùng trong một thủ tục lưu trữ MySQL là. Điều này có nghĩa là ... khó có thể lấy được bản chất chính xác của lỗi.

May mắn thay điều đó không đúng.

SHOW ERRORS LIMIT 1 -- for SQL-state > 2 
SHOW WARNINGS LIMIT 1 -- for SQL-state 1,2 

Sẽ hiển thị lỗi hoặc cảnh báo cuối cùng.

Để ngăn chặn niêm yết mỗi lỗi, bạn có thể xử lý một lớp học của SQL-lỗi như vậy:

SQLWARNING là viết tắt cho lớp các giá trị SQLSTATE bắt đầu với '01'.

NOT FOUND là viết tắt của lớp giá trị SQLSTATE bắt đầu bằng '02'. Điều này chỉ có liên quan trong ngữ cảnh của con trỏ và được sử dụng để kiểm soát những gì xảy ra khi con trỏ đến cuối tập dữ liệu. Nếu không có nhiều hàng hơn, điều kiện Không có dữ liệu xảy ra với giá trị SQLSTATE 02000. Để phát hiện tình trạng này, bạn có thể thiết lập trình xử lý cho nó (hoặc cho một điều kiện NOT FOUND). Một ví dụ được hiển thị trong Phần 12.7.5, “Con trỏ”. Tình trạng này cũng xảy ra đối với SELECT ... INTO câu lệnh var_list không lấy được hàng nào.

SQLEXCEPTION là viết tắt của lớp giá trị SQLSTATE không bắt đầu bằng '00', '01' hoặc '02'.

Vì vậy, để xử lý một ngoại lệ, bạn cần phải chỉ làm:

DECLARE EXIT HANDLER FOR SQLSTATE SQLEXCEPTION .....; 

Links:
http://dev.mysql.com/doc/refman/5.5/en/signal.html
http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html

+1

Cảm ơn Johan. 'SHOW ERRORS' và' SHOW WARNINGS' sẽ hiển thị cho tôi SQLSTATE của lỗi hoặc cảnh báo cuối cùng nếu chạy trong sự cô lập. Tuy nhiên, làm thế nào để tôi truy cập 'trong một thủ tục lưu trữ MySQL'? Đó là, làm thế nào tôi có thể trả về kết quả của 'SHOW ERRORS' hoặc' SHOW WARNINGS' trong một biến đầu ra thủ tục như được mô tả trong câu hỏi ban đầu của tôi? –

0

tôi đang làm hiện giải pháp sau đây: sử dụng một CHỌN để kích động lỗi.Ví dụ:

SELECT RAISE_ERROR_unable_to_update_basket; 

này sẽ dẫn đến việc thông báo lỗi sau (chẳng hạn):

ERROR 1054 (42S22): Unknown column 'RAISE_ERROR_unable_to_update_basket' in 'field list' 

Tôi gói cuộc gọi của tôi đến một thủ tục lưu trữ trong một try {...} catch {.. .} và bây giờ có thể xử lý lỗi này. Điều này tất nhiên sẽ chỉ hoạt động để kích hoạt các thông báo lỗi tùy chỉnh từ bên trong thủ tục lưu sẵn của bạn và sẽ không xử lý bất kỳ lỗi SQL hoặc cơ sở dữ liệu nào, có thể xảy ra (vì mục nhập khóa trùng lặp). Trong trường hợp sau, bạn có thể giải quyết vấn đề này bằng cách sử dụng giải pháp của Johan.

+0

cảm ơn harald. Mặc dù trong trường hợp cụ thể này, tôi đang cố xử lý các lỗi SQL hoặc cơ sở dữ liệu. –

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