【问题标题】:Select information about reference constraints选择有关参考约束的信息
【发布时间】:2016-10-06 21:53:55
【问题描述】:

我正在尝试解决以下问题(使用 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是否可以避免重复并解决这个问题?

【问题讨论】:

    标签: sql oracle11g


    【解决方案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 个其他约束类型
    • 删除所有 rn > 1 的行

    【讨论】:

      猜你喜欢
      • 2021-01-30
      • 2019-03-28
      • 2022-01-15
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      • 2020-09-20
      • 2014-10-23
      • 1970-01-01
      相关资源
      最近更新 更多