我想使用 JDBC 适配器模仿 OpenEdge 中许多数据库具有的自动递增主键功能(即在执行 INSERT 时不必指定主键值)。到目前为止,我已经非常接近我需要的东西,除了能够访问数据库在从 INSERT 返回时生成的主键值的部分(咳咳,所以可能不是那么接近;))。
我当前的解决方案使用表 PK 默认值、触发器和序列的组合来实现它:
CREATE TABLE users (
id BIGINT PRIMARY KEY DEFAULT -1,
name VARCHAR(200)
);
CREATE SEQUENCE users_seq
START WITH 0,
INCREMENT BY 1,
NOCYCLE;
CREATE TRIGGER users_trigger
BEFORE INSERT ON users
REFERENCING NEWROW
FOR EACH ROW
IMPORT
import java.sql.*;
BEGIN
Long current_id = (Long)NEWROW.getValue(1, BIGINT);
if (current_id == -1) {
SQLCursor next_id_query = new SQLCursor("SELECT TOP 1 users_seq.NEXTVAL FROM SYSPROGRESS.SYSCALCTABLE");
next_id_query.open();
next_id_query.fetch();
Long next_id = (Long)next_id_query.getValue(1,BIGINT);
next_id_query.close();
NEWROW.setValue(1, next_id);
}
END
这允许我运行这样的插入语句:
INSERT INTO users(name) VALUES('Foo Bar')
并且新行会自动从数据库触发器中获取一个 ID。那部分工作正常。
我现在真正需要的是设置的 ID 的值;直接获取值,或者包含刚刚插入的行的 ResultSet(然后可以展开以查看 ID)。我知道Oracle和Postgres都支持用于插入的 RETURNING 子句,这通常是如何处理的。但是,对于 OpenEdge,我没有看到类似的东西。
CURRVAL
我可以在 10.2B SQL 开发手册中找到的唯一相关部分是在第 5-10 节中,其中显示了在执行INSERT
that uses之后如何访问序列的NEXTVAL
。INSERT
但是,这很危险,因为如果跨多个 JDBC 会话(竞争条件和诸如此类)为该表执行大量 s,我可以获得其他人的 ID 。
到目前为止,我能想到的唯一选择是编写一个专门用于包装/执行INSERT
操作的存储过程,它具有生成的 ID 的输出参数。但是,这对于我正在处理的工作来说是不可行的,它必须使用普通的 SQLINSERT
语句,而且看起来有点生硬和脆弱(例如,如何处理可以在INSERT
,如果架构发生变化怎么办?)。
此外,这一切的重点是不必在 INSERT 中引用主键,所以请不要告诉我users_seq.NEXTVAL
在我的INSERT
声明中使用。:-)