【问题标题】:Properly implementing auto-incrementing primary keys in OpenEdge 10.2B using SQL / JDBC使用 SQL / JDBC 在 OpenEdge 10.2B 中正确实现自动递增主键
【发布时间】:2012-03-17 21:08:48
【问题描述】:

我想使用 JDBC 适配器模仿 OpenEdge 中许多数据库具有的自动递增主键功能(即在执行 INSERT 时不必指定主键值)。到目前为止,我已经非常接近我需要的东西,除了能够访问数据库在从 INSERT 返回时生成的主键值的部分(咳咳,所以可能不是那么接近;))。

我当前的解决方案使用 table 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,我没有看到类似的东西。

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

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

另外,这样做的重点是不必在 INSERT 中引用主键,所以请不要告诉我在我的 INSERT 语句中使用 users_seq.NEXTVAL。 :-)

【问题讨论】:

    标签: progress-4gl openedge


    【解决方案1】:

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

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

    如果存在一个 SQL 函数,该函数将返回一个特殊的会话 ID,该 ID 对应于客户端与 SQL 引擎的瞬时连接,则可以让客户端和触发器/存储过程使用预先确定的表进行通信。请求队列(通过使用会话 ID 作为键)。不幸的是,根据文档,没有这样的会话 ID。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 它是一个不同语言的数据库适配器,所以重点是 ABL 根本不参与这个过程。 :-)
      猜你喜欢
      • 2015-03-05
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      • 2017-01-09
      • 2014-10-02
      • 1970-01-01
      相关资源
      最近更新 更多