2013-06-07 26 views
7

Tôi bị mắc kẹt. Tôi muốn làm một bảng do người dùng nhập vai mối quan hệ trục và truy vấn của tôi cho đến nay trông như thế này:Động Oracle Pivot_In_Clause

WITH PIVOT_DATA AS (
    SELECT * 
    FROM 
    (
     SELECT USERNAME, GRANTED_ROLE 
     FROM [email protected]_LINK U LEFT OUTER JOIN [email protected]_LINK R 
     ON U.USERNAME = R.GRANTEE 
    ) 
) 
SELECT * 
FROM PIVOT_DATA 
PIVOT 
(
    COUNT(GRANTED_ROLE) 
    FOR GRANTED_ROLE 
    IN('CONNECT') -- Just an example 
) 
ORDER BY USERNAME ASC; 

Nó hoạt động thực sự tốt và không được công việc, nhưng tôi không muốn viết để viết bất kỳ vai trò tôi muốn tìm kiếm trong số pivot_in_clause, bởi vì chúng tôi nhận được hàng tấn chúng và tôi không muốn kiểm tra mọi lúc nếu có bất kỳ thay đổi nào.

Vì vậy, có cách nào để viết SELECT trong pivot_in_clause? Tôi đã tự mình thử:

[...] 
PIVOT 
(
    COUNT(GRANTED_ROLE) 
    FOR GRANTED_ROLE 
    IN(SELECT ROLE FROM [email protected]_LINK) 
) 
[...] 

Nhưng nó luôn mang đến cho tôi một ORA-00936: "thiếu biểu thức" trong dòng 1 của toàn bộ truy vấn và tôi không biết tại sao. Không thể có một số SELECT trong số pivot_in_clause hoặc tôi đang làm sai?

+0

Các vấn đề với mong muốn của bạn là số cột của kết quả là không thể đoán trước/biến. –

+0

@FlorinGhita: Có, tôi phải chạy tập lệnh này trên 5 trường hợp cơ sở dữ liệu khác nhau và số vai trò khác nhau. Đó là lý do tại sao tôi muốn có một phiên bản "động" của tập lệnh này. –

+3

Bạn có thể sử dụng PIVOT XML và sau đó sử dụng (bất kỳ) làm mệnh đề của bạn. Nhược điểm là sau đó nó là vào khách hàng của bạn để phân tích cú pháp xml. – dazedandconfused

Trả lời

6

Bạn có thể xây dựng truy vấn động trong kịch bản của bạn, xem ví dụ này:

variable rr refcursor 

declare 
    bb varchar2(4000); 
    cc varchar2(30000); 
begin 
    WITH PIVOT_DATA AS (
     SELECT * 
     FROM 
     (
      SELECT USERNAME, GRANTED_ROLE 
      FROM DBA_USERS U LEFT OUTER JOIN DBA_ROLE_PRIVS R 
      ON U.USERNAME = R.GRANTEE 
     ) 
    ) 
    select ''''|| listagg(granted_role, ''',''') 
      within group(order by granted_role) || '''' as x 
    into bb 
    from (
     select distinct granted_role from pivot_data 
    ) 
    ; 

    cc := q'[ 
    WITH PIVOT_DATA AS (
     SELECT * 
     FROM 
     (
      SELECT USERNAME, GRANTED_ROLE 
      FROM DBA_USERS U LEFT OUTER JOIN DBA_ROLE_PRIVS R 
      ON U.USERNAME = R.GRANTEE 
     ) 
    ) 
    SELECT * 
    FROM PIVOT_DATA 
    PIVOT 
    (
     COUNT(GRANTED_ROLE) 
     FOR GRANTED_ROLE 
     IN(]' || bb || q'[) -- Just an example 
    ) 
    ORDER BY USERNAME ASC]'; 

    open :rr for cc; 
end; 
/

SET PAGESIZE 200 
SET LINESIZE 16000 
print :rr 

Đây là kết quả (chỉ mảnh nhỏ, bởi vì nó là rất rộng và dài)

----------------------------------------------------------------------------------------------------------------------------------- 
    USERNAME      'ADM_PARALLEL_EXECUTE_TASK' 'APEX_ADMINISTRATOR_ROLE' 'AQ_ADMINISTRATOR_ROLE' 'AQ_USER_ROLE'   
    ------------------------------ --------------------------- ------------------------- ----------------------- ---------------------- 
    ANONYMOUS      0       0       0      0   
    APEX_030200     0       0       0      0   
    APEX_PUBLIC_USER    0       0       0      0  
    APPQOSSYS      0       0       0      0 
.............. 
    IX        0       0       1      1 
    OWBSYS       0       0       1      1  
+0

Oh wow, cảm ơn một bó. Đó là chính xác, những gì tôi đang tìm kiếm. Nó thực sự là một công việc tuyệt vời. :) –