2013-10-24 17 views
5

Tôi đã viết một số chương trình sử dụng hàm WM_CONCAT. Khi tôi chạy truy vấn này:WM_CONCAT with DISTINCT Clause - Gói được biên dịch so với vấn đề truy vấn độc lập

SELECT WM_CONCAT(DISTINCT employee_id) 
FROM employee 
WHERE ROWNUM < 20; 

Nó hoạt động tốt. Khi tôi cố gắng biên dịch truy vấn tương đối giống nhau trong một chức năng gói hoặc thủ tục, nó tạo ra lỗi này: PL/SQL: ORA-30.482: Tùy chọn DISTINCT không cho phép chức năng này

FUNCTION fetch_raw_data_by_range 
RETURN VARCHAR2 IS 

    v_some_string VARCHAR2(32000); 

BEGIN 

    SELECT WM_CONCAT(DISTINCT employee_id) 
    INTO v_some_string 
    FROM employee 
    WHERE ROWNUM < 20; 

    RETURN v_some_string; 

END; 

Tôi nhận ra WM_CONCAT không hỗ trợ chính thức , nhưng ai đó có thể giải thích lý do tại sao nó sẽ hoạt động như một truy vấn độc lập với DISTINCT, nhưng không biên dịch trong một gói?

+1

Bạn sẽ có thể để có được tương tự kết quả với hàm LISTAGG. – OldProgrammer

+2

Tôi đã gắn thẻ này là oracle10g, không cung cấp chức năng đó – Reimius

Trả lời

5

Vấn đề là WM_CONCAT được lưu trữ thủ tục được viết trên pl/sql.

Có một lỗi mở # 9323679: PL/SQL GỌI NGƯỜI DÙNG CHỨC NĂNG ĐƯỢC CHẤP NHẬN NGƯỜI DÙNG VỚI DIILIN DIILIN ORA-30482.

Giải pháp cho các vấn đề như thế này đang sử dụng sql động.

Vì vậy, nếu bạn quấn truy vấn của bạn trong

EXECUTE IMMEDIATE '<your_query>'; 

Sau đó, nó sẽ làm việc.

Nhưng như OldProgrammer đã đề xuất, bạn nên tránh sử dụng WM_CONCAT này.

+0

Bạn có thể cung cấp liên kết đến tài liệu mô tả hành vi này không? – Reimius

+0

@Reimus Xin lỗi, có vẻ như tôi đã trộn lẫn vấn đề này với hành vi 11g mới. Tôi đang sửa câu trả lời này. – Nagh

+0

Ah, do đó, nó là một lỗi và không phải do một số yêu cầu chức năng. Cảm ơn các tài liệu tham khảo. Tôi không có quyền truy cập vào trình theo dõi của họ, nhưng tôi đã có thể tìm thêm bài đăng liên quan đến số lỗi. – Reimius

3

PL/SQL sẽ không cho phép bạn sử dụng distinct trong hàm tổng hợp và vấn đề này cho thấy rằng công cụ SQL và công cụ PL/SQL không sử dụng cùng một trình phân tích cú pháp.

Một trong những giải pháp cho vấn đề này là sử dụng truy vấn phụ như dưới đây,

SELECT WM_CONCAT(employee_id) 
INTO v_some_string 
FROM (select DISTINCT employee_id 
     FROM employee) 
WHERE ROWNUM < 20; 

Một giải pháp khác là sử dụng SQL động như Nagh đề nghị,

FUNCTION fetch_raw_data_by_range 
RETURN VARCHAR2 IS 

    v_some_string VARCHAR2(32000); 
    v_sql VARCHAR2(200); 

BEGIN 

    v_sql :='SELECT WM_CONCAT(DISTINCT employee_id) 
      FROM employee 
      WHERE ROWNUM < 20'; 

    execute immediate v_sql INTO v_some_string; 
    RETURN v_some_string; 
END; 
+0

Tôi nhận ra rằng trình phân tích cú pháp pl/sql không giống với trình phân tích cú pháp truy vấn, nhưng điều tôi thực sự muốn biết là tại sao nó xảy ra, tức là quy tắc tại chỗ nào gây ra hành vi này. Có thể có lý do chính xác DISTINCT không được phép trong một số trường hợp cụ thể trong pl/sql mà ví dụ của tôi ở đây là một ví dụ tập hợp con và không đại diện cho 'vấn đề' nói chung. – Reimius

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