2016-10-06 24 views
0

我想解決以下問題(使用Oracle 11g數據庫):我需要使用ALL_CONS_COLUMNS表獲取所有表列以及有關引用約束(此列引用的表和列的名稱)的信息,例如:選擇關於參考約束的信息

No. Column  Details 
--- ----------- ------------------------------------------------------ 
    1 foo_id  Type : NUMBER(9) 
        Constr : "foo_fk" References foo_table(id) 

    2 bar_id  Type : NUMBER(9) 
        Constr : "bar_fk" References bar_table(id) 

    2 date_created Type : Date 

有關表的約束存儲在ALL_CONSTRAINTS信息,約束(表和列名)在ALL_CONS_COLUMNS商店的詳細描述。 現在我有了這個代碼:

SELECT 
    ROWNUM as "No.", 
    t.COLUMN_NAME as "Имя столбца", 
    'Type: ' || t.DATA_TYPE || (SELECT CASE 
      WHEN ac.CONSTRAINT_TYPE = 'R' 
      THEN chr(10) || 'Constr: ' || allcc.CONSTRAINT_NAME || 
      ' References ' || (SELECT TABLE_NAME FROM ALL_CONS_COLUMNS WHERE CONSTRAINT_NAME = ac.R_CONSTRAINT_NAME) || 
      '(' || (SELECT COLUMN_NAME FROM ALL_CONS_COLUMNS WHERE CONSTRAINT_NAME = ac.R_CONSTRAINT_NAME) || ')' 
      ELSE '' 
      END AS Contype FROM DUAL) As "Атрибуты", 
    ac.CONSTRAINT_TYPE 

FROM 
    ALL_CONS_COLUMNS allcc 

INNER JOIN 
    ALL_TAB_COLUMNS t 
    ON t.TABLE_NAME = allcc.TABLE_NAME 
    AND t.COLUMN_NAME = allcc.COLUMN_NAME 

INNER JOIN 
    (SELECT (CASE WHEN CONSTRAINT_TYPE = 'R' THEN 'R' ELSE NULL END) as CONSTRAINT_TYPE, CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS) ac 
    ON ac.CONSTRAINT_NAME = allcc.CONSTRAINT_NAME 

WHERE 
    t.TABLE_NAME = 'SUPPLIES'; 

但是,如果列有超過1層的約束,它會在輸出複製每個約束:

No. Column    Details: 
1 ID_SUPPLIER   Type: NUMBER  
2 ID_SHOP    Type: NUMBER  
3 DATE_SUPPLY   Type: DATE 
4 ID     Type: NUMBER  
5 ID_SHOP    Type: NUMBER 
         Constr: FK_SUPPLIES_SHOP References SHOPS(ID) 
6 ID_SUPPLIER   Type: NUMBER 
         Constr: FK_SUPPLIES_SUPPLIER References SUPPLIERS(ID) 

在這個例子中ID_SUPPLIER重複兩次2個約束(引用和非null)。 是否有可能在不使用PL \ SQL的情況下避免重複並解決此問題?

回答

1

你可以使用窗口函數來擺脫重複的行;這裏,我使用ROW_NUMBER()

select rownum as no, 
     v1.* 
    from (SELECT t.COLUMN_NAME, 
       'Type: ' || t.DATA_TYPE || 
       (SELECT CASE 
         WHEN ac.CONSTRAINT_TYPE = 'R' THEN 
          chr(10) || 'Constr: ' || allcc.CONSTRAINT_NAME || ' References ' || 
          (SELECT TABLE_NAME 
          FROM ALL_CONS_COLUMNS 
          WHERE CONSTRAINT_NAME = ac.R_CONSTRAINT_NAME) || '(' || 
          (SELECT COLUMN_NAME 
          FROM ALL_CONS_COLUMNS 
          WHERE CONSTRAINT_NAME = ac.R_CONSTRAINT_NAME) || ')' 
         ELSE 
          '' 
         END AS Contype 
        FROM DUAL) As description, 
       ac.CONSTRAINT_TYPE, 
       row_number() over(partition by allcc.column_name order by(case constraint_type 
       when 'R' then 
        1 
       else 
        2 
       end)) as rn 
      FROM ALL_CONS_COLUMNS allcc 
     INNER JOIN ALL_TAB_COLUMNS t 
      ON t.TABLE_NAME = allcc.TABLE_NAME 
      AND t.COLUMN_NAME = allcc.COLUMN_NAME 
     INNER JOIN (SELECT (CASE 
          WHEN CONSTRAINT_TYPE = 'R' THEN 
           'R' 
          ELSE 
           NULL 
          END) as CONSTRAINT_TYPE, 
          CONSTRAINT_NAME, 
          R_CONSTRAINT_NAME 
         FROM ALL_CONSTRAINTS) ac 
      ON ac.CONSTRAINT_NAME = allcc.CONSTRAINT_NAME 
     WHERE t.TABLE_NAME = 'SUPPLIES') v1 
where rn = 1; 

  • 分配RN = 1到各參照約束
  • 分配RN = 1到其它的約束類型,如果沒有參照關係約束存在對於相同的柱(除非列上存在另一個非參照約束;在這種情況下,只有其中一個獲得rn = 1)
  • 如果存在參照約束,則分配rn> 1個其他約束類型
  • 刪除所有行,其中> 1