选择有关参考约束的信息

时间:2016-10-06 13:32:12

标签: sql oracle11g

我正在尝试解决以下问题(使用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';

但是如果列具有多个约束,则它将在每个约束的输出中重复:

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 个答案:

答案 0 :(得分: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>其他约束类型(如果存在引用约束)
  • 删除其rn>的所有行1