1

我想使用 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)。我知道OraclePostgres都支持用于插入的 RETURNING 子句,这通常是如何处理的。但是,对于 OpenEdge,我没有看到类似的东西。

CURRVAL我可以在 10.2B SQL 开发手册中找到的唯一相关部分是在第 5-10 节中,其中显示了在执行INSERTthat uses之后如何访问序列的NEXTVALINSERT但是,这很危险,因为如果跨多个 JDBC 会话(竞争条件和诸如此类)为该表执行大量 s,我可以获得其他人的 ID 。

到目前为止,我能想到的唯一选择是编写一个专门用于包装/执行INSERT操作的存储过程,它具有生成的 ID 的输出参数。但是,这对于我正在处理的工作来说是不可行的,它必须使用普通的 SQLINSERT语句,而且看起来有点生硬和脆弱(例如,如何处理可以在INSERT,如果架构发生变化怎么办?)。

此外,这一切的重点是不必在 INSERT 中引用主键,所以请不要告诉我users_seq.NEXTVAL在我的INSERT声明中使用。:-)

4

2 回答 2

1

没有可行的方法来实现这一点;用户必须为 PK 指定一个值或指定序列的名称,以便可以使用CURRVAL/ 。NEXTVAL

一种不可行的解决方法是构建一个专门用于执行 INSERT(s) 的特殊存储过程,但这不是通用解决方案,因为 INSERT 命令采用可变数量的参数(尤其是要填充哪些列和数据) ,而存储过程必须有固定数量的参数。

If there existed a SQL function that would return a special session ID that corresponded to the client's transient connection to the SQL engine, it would be possible to have the client and trigger/stored procedure communicate using a pre-determined table as a request queue (by using the session ID as a key). Unfortunately, according to the documentation there is no such session ID.

于 2012-06-12T18:45:26.230 回答
-2

1 个愚蠢的问题...为什么要使用此 SQL 代码来更新正在进行的数据数据库?它在 4GL (resp. ABL) 代码中变得更容易......您应该在应用服务器上创建一个简单的创建过程或服务。我从迁移工具(勺子)访问 ODBC SQL 时遇到了同样的问题。我必须放弃...

于 2012-05-15T10:05:49.357 回答