在您不介意删除的H2DB上尝试以下操作。 警告。这会对数据库造成不可破坏的损害!
使用自引用默认列创建表。例如,使用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
);
关闭连接并关闭数据库。
再次启动数据库并尝试连接。错误时观察连接失败:
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)
顺便说一句。请不要回复“使用auto_increment
”。是的,我知道auto_increment
列。回滚后自动增量列留下间隙,不处理所有数据类型。例如,如何自动递增应用程序使用不是“添加常量整数?”的算法的列。此外,没有办法auto_increment
一个VARCHAR
,但你的应用程序可能有一个非常明智的概念。
答案 0 :(得分: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;
顺便说一下,'brick'是相对的...你仍然可以使用Recover工具检索数据。但当然它并不好,并将在下一个版本中修复。问题是H2不限制你在default子句中可以做的事情。其他数据库根本不允许在default子句中进行任何查询,但我认为这是胆小的(这是正确的词吗?),我会尝试找到更好的解决方案(可能允许它)。你有什么建议?