2014-02-10 39 views
0

我有以下表:ROLE,PRIVILEGE和ROLE_PRIV。每個角色和每個權限都有唯一的ID和名稱,而ROLE_PRIV包含兩個表之間的鏈接,這表明每個角色的權限(每個角色ID + priv ID組合都是唯一的)。SQL返回一個表的所有值和YES/NO(如果存在於另一個表中)的過程

我想生成一個報告,其中我將有一個具有所有權限的列,頂行列出所有角色ID,然後在下面的單元格中顯示YES/NO,指示此角色是否具有指定的特定權限。

我會非常感謝任何能夠給我提供關於是否可以創建查詢或PL/SQL過程來設置此報告的指導的人員。我很好地獲得只有一個角色的信息,因爲他們通常不超過10次,重複查詢/過程10次對我來說不會是一個問題。

我對SQL有一定的經驗,對PL/SQL很少有經驗,但是如果給出好的指針,就足以對某些東西進行修補。

感謝您花時間閱讀本文。 :)

回答

1

如果您使用11g或更高版本的Oracle,將行轉換爲列的最簡單方法是PIVOT運算符(documentation)。例如,考慮此查詢 - 它會給你所有的角色和權限的表與他們對應的值:

SELECT * FROM 
(SELECT fj.role_name, fj.priv_name, DECODE(rp.val,1,'YES',0,'NO','-') VAL 
FROM (SELECT r.id role_id, r.name role_name, p.id priv_id, p.name priv_name 
     FROM ROLE r, PRIVILEGE p) fj 
     LEFT JOIN ROLE_PRIV rp ON fj.role_id = rp.role_id AND fj.priv_id = rp.priv_id) 
PIVOT (MAX(VAL) FOR PRIV_NAME IN (list_of_privileges)) 
ORDER BY ROLE_NAME 

但是有這樣的解決一個問題:你需要來命名IN子句每個特權(或使用XML關鍵字,但它會弄亂結果),但是,考慮到特權列表應該不經常更改,這應該不成問題。下面的例子:

WITH ROLE AS (SELECT 1 ID, 'ROLE1' NAME FROM DUAL 
       UNION 
       SELECT 2 ID, 'ROLE2' NAME FROM DUAL 
       UNION 
       SELECT 3 ID, 'ROLE3' NAME FROM DUAL), 
    PRIVILEGE AS (SELECT 1 ID, 'READ' NAME FROM DUAL 
        UNION 
        SELECT 2 ID, 'WRITE' NAME FROM DUAL 
        UNION 
        SELECT 3 ID, 'EXECUTE' NAME FROM DUAL), 
    ROLE_PRIV AS (SELECT 1 ROLE_ID, 1 PRIV_ID, 1 VAL FROM DUAL 
        UNION 
        SELECT 1 ROLE_ID, 2 PRIV_ID, 0 VAL FROM DUAL 
        UNION 
        SELECT 2 ROLE_ID, 1 PRIV_ID, 1 VAL FROM DUAL 
        UNION 
        SELECT 2 ROLE_ID, 2 PRIV_ID, 0 VAL FROM DUAL 
        UNION 
        SELECT 3 ROLE_ID, 1 PRIV_ID, 0 VAL FROM DUAL 
        UNION 
        SELECT 3 ROLE_ID, 3 PRIV_ID, 1 VAL FROM DUAL) 
SELECT * FROM 
(SELECT fj.role_name, fj.priv_name, DECODE(rp.val,1,'YES',0,'NO','-') VAL 
FROM (SELECT r.id role_id, r.name role_name, p.id priv_id, p.name priv_name 
     FROM ROLE r, PRIVILEGE p) fj 
     LEFT JOIN ROLE_PRIV rp ON fj.role_id = rp.role_id AND fj.priv_id = rp.priv_id) 
PIVOT (MAX(VAL) FOR PRIV_NAME IN ('READ','WRITE','EXECUTE')) 
ORDER BY ROLE_NAME 

會給你以下結果:

ROLE_NAME 'READ' 'WRITE' 'EXECUTE' 
ROLE1 YES NO - 
ROLE2 YES NO - 
ROLE3 NO - YES 

如果你使用的是Oracle的早期版本,您可以考慮選擇不同的解決方案(like this one)。


好吧,如果你不能使用PIVOT操作,以獲得所需的輸出最簡單的方法應該是這樣的查詢:

SELECT p.name, DECODE((SELECT VAL 
         FROM ROLE_PRIV rp 
         WHERE rp.role_id = (SELECT ID 
              FROM ROLE r 
              WHERE r.name = :ROLE_NAME) 
          AND rp.priv_id = p.id), 
         1, 'YES', 
         0, 'NO', 
         '-') :ROLE_NAME 
FROM PRIVILEGE p 

您可以只需添加另一種添加addtional角色來此查詢柱。例如,查看此查詢:

WITH ROLE AS (SELECT 1 ID, 'ROLE1' NAME FROM DUAL 
       UNION 
       SELECT 2 ID, 'ROLE2' NAME FROM DUAL 
       UNION 
       SELECT 3 ID, 'ROLE3' NAME FROM DUAL), 
    PRIVILEGE AS (SELECT 1 ID, 'READ' NAME FROM DUAL 
        UNION 
        SELECT 2 ID, 'WRITE' NAME FROM DUAL 
        UNION 
        SELECT 3 ID, 'EXECUTE' NAME FROM DUAL), 
    ROLE_PRIV AS (SELECT 1 ROLE_ID, 1 PRIV_ID, 1 VAL FROM DUAL 
        UNION 
        SELECT 1 ROLE_ID, 2 PRIV_ID, 0 VAL FROM DUAL 
        UNION 
        SELECT 2 ROLE_ID, 1 PRIV_ID, 1 VAL FROM DUAL 
        UNION 
        SELECT 2 ROLE_ID, 2 PRIV_ID, 1 VAL FROM DUAL 
        UNION 
        SELECT 3 ROLE_ID, 1 PRIV_ID, 0 VAL FROM DUAL 
        UNION 
        SELECT 3 ROLE_ID, 3 PRIV_ID, 1 VAL FROM DUAL) 
SELECT p.name, 
     DECODE((SELECT VAL 
       FROM ROLE_PRIV rp 
       WHERE rp.role_id = (SELECT ID 
            FROM ROLE r 
            WHERE r.name = 'ROLE1') 
        AND rp.priv_id = p.id), 
       1, 'YES', 
       0, 'NO', 
       '-') ROLE1, 
     DECODE((SELECT VAL 
       FROM ROLE_PRIV rp 
       WHERE rp.role_id = (SELECT ID 
            FROM ROLE r 
            WHERE r.name = 'ROLE2') 
        AND rp.priv_id = p.id), 
       1, 'YES', 
       0, 'NO', 
       '-') ROLE2, 
     DECODE((SELECT VAL 
       FROM ROLE_PRIV rp 
       WHERE rp.role_id = (SELECT ID 
            FROM ROLE r 
            WHERE r.name = 'ROLE3') 
        AND rp.priv_id = p.id), 
       1, 'YES', 
       0, 'NO', 
       '-') ROLE3 
FROM PRIVILEGE p 

它會爲您提供三種角色的結果。


像這樣的東西應該工作:

SELECT p.name, 
     DECODE((SELECT COUNT(1) 
       FROM ROLE_PRIV rp 
       WHERE rp.role_id = (SELECT ID 
            FROM ROLE r 
            WHERE r.name = 'ROLE1') 
        AND rp.priv_id = p.id), 
       0, 'NO', 
       'YES') ROLE1 
FROM PRIVILEGE p 
+0

感謝這麼多的翔實的答案! :) – user3236074

+0

再次你好!我查看了你給我的信息,我不確定這是我要找的。我們使用的客戶端是10g,所以我們不能使用PIVOT。與此同時,我並不想將行變成列,而是使用類似於SQL中的excell VLOOKUP公式的東西。 *繼續* – user3236074

+0

我想在第一列中有select * from特權,第二列爲特定角色返回數據(例如,調查員)以及是否具有特定的權限。換句話說,如果ROLE_PRIV中有一個指示說明角色具有來自第一列的特定權限,並且在一個步驟中基本上爲每個特權重複此操作,則返回yes。因此,最終結果將是PRIVILEGES列(包含所有priv)和包含YES/NO的列調查器,指示調查員是否擁有權限。 – user3236074

相關問題