2009-11-04 72 views
8

我試圖找到使用Java(在Oracle數據庫上,但應該沒有區別)的表的唯一約束。查找數據庫表的唯一約束條件

由於DatabaseMetaData的getPrimaryKeys(....),我發現了一種發現表的主鍵的方法; 但是,我無法找到表的獨特的constaints,互聯網是無法幫助我,因此我在這裏結束詢問我的問題:)

有沒有一種乾淨的方式來找到唯一的約束(或者,相反,列的名稱必須是唯一的表......那麼你得到它嘿)一張桌子? 最好的問候,

尼爾斯

+0

因此,我收集你寧願沒有Oracle特定的解決方案? – DCookie

回答

20

可以查詢數據字典:

SQL> SELECT cc.* 
    2 FROM all_constraints c 
    3 JOIN all_cons_columns cc ON (c.owner = cc.owner 
    4        AND c.constraint_name = cc.constraint_name) 
    5 WHERE c.constraint_type = 'U' 
    6  AND c.table_name = 'T'; 

OWNER  CONSTRAINT_NAME TABLE_NAME  COLUMN_NAME  POSITION 
---------- ----------------- -------------- ------------- ---------- 
VNZ  UNIQUE_COL  T    COLUMN1    1 
VNZ  UNIQUE_COL  T    COLUMN2    2 
VNZ  UNIQUE_COL2  T    COLUMN2    1 
+1

謝謝文森特,這是我正在尋找的!非常感謝 ! – Nils

0

如果甲骨文唯一約束創建索引(我不知道,如果是的話,你需要檢查),比您可以通過getIndexInfo()

+0

是的,Oracle在UNIQUE約束中標識的任何列上創建一個唯一索引 - 這就是它強制唯一性的方式。 – DCookie

+0

但是,唯一索引可能完全以Oracle爲中心。如果需要通用的解決方案,這在所有情況下可能都不是這樣。 – DCookie

+0

而且,我認爲Oracle也可以使用非唯一索引來執行唯一約束。 – erikkallen

0

瞭解您的限制約束通常由索引強制執行。也許使用DatabaseMetaData.getIndexInfo()找到非唯一性爲假的索引?

0

由於大多數數據庫都將這些約束條件存儲爲索引,因此可以使用DatabaseMetaData.getIndexInfo()(如前所述)。這在使用Postgresql時效果很好。

與第4個參數來調用getIndexInfo()true這是唯一重要的,因爲documenation說:

unique - 如果爲true,只返回唯一值的索引;當假,無論是否獨特與否

用下面的代碼 回報指數:

// Class to combine all columns for the same index into one object 
public static class UniqueConstraint { 
    public String table; 
    public String name; 
    public List<String> columns = new ArrayList<>(); 
    public String toString() { 
     return String.format("[%s] %s: %s", table, name, columns); 
    } 
} 

public static List<UniqueConstraint> getUniqueConstraints(Connection conn, String schema, String table) throws SQLException { 
    Map<String, UniqueConstraint> constraints = new HashMap<>(); 

    DatabaseMetaData dm = conn.getMetaData(); 
    ResultSet rs = dm.getIndexInfo(null, schema, table, true, true); 
    while(rs.next()) { 
     String indexName = rs.getString("index_name"); 
     String columnName = rs.getString("column_name"); 

     UniqueConstraint constraint = new UniqueConstraint(); 
     constraint.table = table; 
     constraint.name = indexName; 
     constraint.columns.add(columnName); 

     constraints.compute(indexName, (key, value) -> { 
      if (value == null) { return constraint; } 
      value.columns.add(columnName); 
      return value; 
     }); 
    } 

    return new ArrayList<>(constraints.values()); 
} 

您可以撥打:

getUniqueConstraints(conn, "public", tableName); 

,並取回所有的獨特的列表給定表的約束。約束按索引分組,因爲一個索引可以覆蓋多個列,如果它們只是組合的唯一列。