2011-06-14 72 views
1

請在您不介意刪除的H2DB上嘗試以下操作。 警告。這將不可避免地損壞數據庫!自引用列可能會損壞H2數據庫

  1. 創建一個帶有自引用默認列的表。例如,使用alter table修改普通表:

    create table if not exists BRICK_H2(ID tinyint); 
    alter table BRICK_H2 alter column ID set default ifnull(
        (select max(ID) from BRICK_H2 for update)+1,0 
    ); 
    
  2. 關閉連接和關閉數據庫。

  3. 再次啓動數據庫並嘗試連接。觀察連接失敗的錯誤:

 
Table "BRICK_H2" not found; SQL statement: 
CREATE CACHED TABLE PUBLIC.BRICK_H2(
    ID TINYINT DEFAULT IFNULL(((SELECT 
    MAX(ID) 
FROM PUBLIC.BRICK_H2 
    /* PUBLIC.BRICK_H2.tableScan */ 
FOR UPDATE) + 1), 0) 
) [42102-155] 42S02/42102 (Help) 

BTW。請不要回復「使用auto_increment」。是的,我知道auto_increment列。自動遞增列在回滾後留下間隙,不處理所有數據類型。例如,如何自動增加應用程序使用不是「添加常量整數?」的算法的列?此外,沒有辦法令人信服地auto_increment a VARCHAR,但您的應用程序可能有一個完全合理的概念。

+2

我想這個問題是 「我怎樣才能得到相同的行爲,而不磚砌我的數據庫?」* - 因爲否則這是一個錯誤報告,而不是StackOverflow的問題。 – Tomalak 2011-06-14 19:10:54

回答

3

一種解決方案是使用Java的功能,如:

drop all objects; 
create table if not exists do_not_brick(id int); 
create alias query as $$ 
String query(Connection conn, String sql) throws SQLException { 
    ResultSet rs = conn.createStatement().executeQuery(sql); 
    rs.next(); 
    return rs.getString(1); 
}$$; 
alter table do_not_brick alter column id set default 
ifnull(query('select max(id) from do_not_brick for update')+1, 0); 
insert into do_not_brick() values(),(),(); 
select * from do_not_brick; 

順便說一句,「磚」是相對的...你仍然可以檢索使用恢復工具數據。但是,這當然不好,並且會在下一個版本中修復。問題在於H2不限制你可以在默認子句中做什麼。其他數據庫根本不允許在默認子句中進行任何查詢,但我認爲這很膽小(這是正確的詞?),我會嘗試找到一個更好的解決方案(可能允許它)。你有什麼建議?

+0

+1是的,[膽小](http://www.google.com/search?&rls=en&q=timid)是[motit juste](http://zh.wiktionary.org/wiki/mot_juste)。 – trashgod 2011-06-14 21:41:57