将序列从postgres迁移到DB2的创建表的方法

时间:2014-05-30 22:02:34

标签: db2 sequence benchmarking identity

我需要将DDL从Postgres迁移到DB2,但我需要它与Postgres中的相同。有一个表从序列生成值,但也可以明确给出值。

的Postgres

create sequence hist_id_seq;

create table benchmarksql.history (
  hist_id  integer not null default nextval('hist_id_seq') primary key,
  h_c_id   integer,
  h_c_d_id integer,
  h_c_w_id integer,
  h_d_id   integer,
  h_w_id   integer,
  h_date   timestamp,
  h_amount decimal(6,2),
  h_data   varchar(24)
);

(查看hist_id列中的序列调用以定义主键的值)

业务逻辑通过显式提供ID插入表中,在其他情况下,它会离开数据库以选择数字。

如果我在DB2中将其更改为GENERATED ALWAYS,则会抛出错误,因为有一些提供的值。另一方面,如果我使用GENERATED BY DEFAULT创建表,DB2将在尝试使用相同的值(SQL0803N)插入时抛出错误,因为“内部序列”没有考虑已插入的值,并且它不会使用下一个值重试。

并且,每次插入提供的ID时,我都不想重新启动序列。

这是BenchmarkSQL在尝试将其移植到DB2时的问题:https://sourceforge.net/projects/benchmarksql/(File sqlTableCreates)

如何在DB2中实现与Postgres中相同的数据库逻辑(显然在Oracle中)?

1 个答案:

答案 0 :(得分:0)

您在误解下操作:数据库外部的源可以指示其内部键。理想情况/概念上,自动生成的ID永远不需要在数据库外部看到,因为从概念上讲,应该有独特的自然键用于导出或报告。尽管如此,有时应用程序需要管理一些ID,通常是在设置相关实体​​时(例如,JPA似乎希望以这种方式工作)。

但是,如果添加从不同来源生成的id值,则db无法管理它。怎么可能呢?这样做效率不高 - 一方面,尝试这样做会做以下其中一种

  1. 面对多个客户端(尝试添加重复的密钥)时不安全
  2. 序列化对表的访问(对于可能很慢的查询)
  3. (这通常会出现在人们尝试类似:SELECT MAX(id) + 1的情况时,这需要锁定整个表格以确保线程安全,可能包括甚至不会触及该列的语句。如果您尝试查找任何"首先未使用的" id - 尝试填补空白 - 这会变得更加复杂和有问题)

    两者都不理想,所以最好不要首先解决问题。这通常是通过自动生成id列来完成的,但是(如前所述)有些情况下我们可能需要知道在将行插入表之前id是什么。幸运的是,有一个标准的SQL对象SEQUENCE。这提供了一种数据库管理,线程安全,快速获取ID的方法。看来在PostgreSQL中你可以使用DEFAULT子句中的序列作为列,但DB2并不允许它。如果你不想每次都指定一个id(它应该在某些时候自动生成),你需要另一种方式;这是使用BEFORE INSERT触发器的最佳时机;

    CREATE TRIGGER Add_Generated_Id NO CASCADE BEFORE INSERT ON benchmarksql.history
                   NEW AS Incoming_Entity
                   FOR EACH ROW
                   WHEN Incoming_Entity.id IS NULL
                   SET id = NEXTVAL FOR hist_id_seq
    

    (类似这样的事情 - 没有经过测试。你没有指明项目属于哪个地方)

    所以,如果你然后添加一行像:

    INSERT INTO benchmarksql.history (hist_id, h_data) VALUES(null, 'a')
    

    INSERT INTO benchmarksql.history (h_data) VALUES('a')
    

    将自动生成并附加ID。请注意,添加到表中的 ALL ID必须来自给定的序列(正如@mustaccio指出的那样,即使在PostgreSQL中也是如此),或者列上的任何UNIQUE CONSTRAINT都将启动抛出重复键错误。因此,只要您的应用程序在表格中插入行之前需要id,您就需要某种形式的

    SELECT NEXT VALUE FOR hist_id_seq
    FROM sysibm.sysdummy1
    

    ......那就是它,差不多。这完全是线程和并发安全的,不会维护/需要长期锁定,也不需要序列化访问表。