2010-10-15 58 views
15

Nếu câu lệnh SELECT INTO không trả lại ít nhất một hàng, thì ORA-01403 được ném.Tại sao no_data_found ORA-01403 là ngoại lệ trong Oracle?

Đối với mọi DBMS khác, tôi biết điều này là bình thường đối với CHỌN. Chỉ Oracle xử lý một INTO SELECT như thế này.

CREATE OR REPLACE PROCEDURE no_data_proc IS 
    dummy dual.dummy%TYPE; 
BEGIN 
    BEGIN 
    SELECT dummy 
     INTO dummy 
     FROM dual 
     WHERE dummy = 'Y'; 
    EXCEPTION 
    WHEN no_data_found THEN 
     dbms_output.put_line('Why is this needed?'); 
    END; 
END no_data_proc; 

Tại sao?

Theo tôi, bạn không cần ngoại lệ này thực sự. Đó là quá nhiều chi phí. Đôi khi nó rất tiện dụng nhưng bạn phải viết toàn bộ BEGIN, EXCEPTION, WHEN, END Block.

Có bất kỳ lý do quan trọng nào mà tôi không thấy không?

+5

Đừng quên bắt QUÁ_MIN_ROWS khi chọn trả về nhiều hàng. – Rene

Trả lời

18

Khối ngoại lệ không cần thiết , bạn có thể sử dụng nó hay không, tùy thuộc vào ngữ cảnh.

Ở đây bạn đang tích cực bỏ qua ngoại lệ (các thủ tục sẽ trở thành công) nhưng phần lớn thời gian nếu bạn đang làm một SELECT INTO bạn muốn nó thất bại nếu nó không trả về một hàng, xem xét:

PROCEDURE update_employee_salary (p_empno) IS 
    l_salary NUMBER; 
BEGIN 
    SELECT sal INTO l_salary FROM emp WHERE empno = p_empno FOR UPDATE; 
    /* do something with emp data */ 
END; 

Ở đây tôi muốn chức năng của tôi thất bại nếu được gọi với số empno không tồn tại trong bảng EMP. Tôi có thể bắt các ngoại lệ để nâng cao một thông báo lỗi có ý nghĩa (với raise_application_error) nhưng hầu hết thời gian tôi hài lòng với ORA-01403.

Nói chung, ngoại lệ duy nhất bạn nên nắm bắt là ngoại lệ dự kiến ​​(nghĩa là đây không phải là tiêu chuẩn để bắt tất cả ORA-01403 hoặc tất cả ngoại lệ cho vấn đề đó).

+0

SELECT INTO FOR UPDATE là một ví dụ điển hình. Thx –

2

Vì bạn đang thực hiện SELECT INTO yêu cầu chính xác một hàng (nhiều hàng hơn cũng sẽ là một lỗi).

Nếu bạn có thể có một hoặc không có hàng, bạn có thể sử dụng con trỏ.

Nó không phải là công việc của cơ sở dữ liệu để quyết định cho bạn rằng một hàng bị thiếu không phải là một lỗi, và chỉ cần đặt giá trị thành rỗng.

6

Bạn có thể thử sử dụng MIN để tránh sử dụng mệnh đề EXCEPTION.

SELECT MIN(dummy) 
    INTO dummy 
    FROM dual 
    WHERE dummy = 'Y'; 

sau đó biến giả sẽ được NULL

+0

Vâng, đó là những gì tôi làm, quá. – Thilo

+0

Nếu bạn có quá nhiều hàng thì sao? Sau đó, bạn sẽ chọn hàng min có thể sai. –

+1

@ user411718, Nếu bạn mong đợi có một vài hàng, tại sao bạn thử lưu nó trong biến? Tôi chỉ sử dụng MIN cho các trường hợp khi tôi có thể nhận được một hoặc không có hàng, để tránh sử dụng EXCEPTION. Và những gì tôi cần: chỉ là một giá trị hoặc NULL. –

11

Nhưng chúng tôi vẫn cần trả lời câu hỏi "tại sao ngoại lệ được ném trong trường hợp SELECT không có dữ liệu được truy lục".

Tôi tin rằng điều này được thực hiện vì đó là một tình huống phổ biến mà có thể bị bỏ qua. Viết code như thể nó luôn luôn mong muốn tìm kiếm dữ liệu là một điều phổ biến để làm, và nếu chúng ta đã dự định đưa vào kiểm tra lỗi như

SELECT <something...> 
IF SQLCODE = 100 THEN -- No data found 
    <no-data handler> 
END IF 

có khả năng IMHO rằng việc kiểm tra cho SQLCODE = 100 sẽ bị bỏ qua thường xuyên. Có một ngoại lệ làm rams nó ngay lên mũi của bạn rằng A) một điều kiện quan trọng (không tìm thấy dữ liệu) xảy ra, và B) NO ALLOWANCE được thực hiện cho điều này.IMO có động cơ PL/SQL nâng cao một ngoại lệ tốt hơn là có chương trình tiếp tục vui vẻ trên con đường của nó theo giả định rằng dữ liệu được lấy ra khi thực tế nó không phải, điều này có thể dẫn đến tất cả các vấn đề khác.

Chia sẻ và thưởng thức.

+0

+1 phản hồi tuyệt vời. –

1

Vì không rõ động cơ PL/SQL nên làm gì - nên nó có thoát khỏi khối không? Nó có nên bấm với NULL trong biến không? Điều gì sẽ xảy ra nếu trong khối tiếp theo bạn cố gắng chèn nó vào cột NOT NULL, nó nên báo cáo vị trí của lỗi như thế nào? Làm cho nó trở thành một ngoại lệ buộc bạn phải rõ ràng về nó.

1

Bạn cũng có thể sử dụng các chức năng sql MAX hoặc MIN. Nếu không có hàng nào được trả về thì các hàm này sẽ trả về một NULL.

Ví dụ: Chọn MAX (column1) Into biến Từ Bảng đâu COLUMN1 = 'Giá trị';

Hàm MAX sẽ trả về giá trị lớn nhất hoặc nếu không có hàng nào được trả về thì nó sẽ trả về NULL.

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