2016-10-06 13 views
0

次の問題(Oracle 11gデータベース)を解決しようとしています。ALL_CONS_COLUMNSテーブルを使用してすべてのテーブル列を取得する必要があり、参照制約(この列で参照されるテーブルと列の名前)例えば:ALL_CONSTRAINTSでテーブルの制約店、制約(テーブルやカラム名)の詳細な記述店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 

情報。

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つの以上の制約がある場合、それは各制約のために、出力に複製されます:この例のID_SUPPLIERの重複で

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) 

二度のために、今、私はこのコードを持っているために 2制約(参照および非NULL)。 重複を避け、PL \ SQLを使用せずにこの問題を解決できますか?

答えて

1

ウィンドウ関数を使用して重複行を削除することができます。ここで、Iは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を代入します列に別の非参照制約がない場合は、そのうちの1つのみがrn = 1を取得します)
  • 参照制約が存在する場合、rn> 1の他の制約タイプを割り当てます。
  • は、rn> 1のすべての行を削除します。
関連する問題