Postgres中多次插入序列失败

时间:2015-01-26 05:30:02

标签: java sql postgresql liquibase

有一个带有多个值的插入查询(大约18k):

INSERT INTO ENTRIES (ID, USER_ID) 
VALUES (nextval('my_seq'), '233'),(nextval('my_seq'), '233');

这是从java应用程序中的liquibase changeset触发的:

JdbcConnection connection = (JdbcConnection) database.getConnection();

        ResultSet resultSet = connection.prepareStatement("SELECT ID FROM USERS").executeQuery();

        List<String> values = new ArrayList<>();

        while (resultSet.next()) {
            Long userId = resultSet.getLong(1);

            for (int i = 0; i < 3; i++) {
                values.add("(nextval('my_seq'), '" + userId + "')");
            }
        }

        String sql = "INSERT INTO ENTRIES (ID, USER_ID) VALUES " + join(values, ",") + ";";

        connection.createStatement().execute(sql);

当它针对h2数据库执行时,一切都很好,但是当我针对postgres运行时,会抛出以下异常:

duplicate key value violates unique constraint "entries_pkey"

像来自sequance的id正在被重用。

在pgAdmin中运行sql时一切正常,但是从第一次插入时应用程序失败。

我的第一个想法是,sql应该以不同的方式执行。

对此有何想法?

以下是表格说明:

  CREATE TABLE entries
(
  id bigint NOT NULL,
  user_id bigint,
  CONSTRAINT entries_pkey PRIMARY KEY (id),
  CONSTRAINT fk_e3udjwux3ly7lu31huish0f82 FOREIGN KEY (user_id)
      REFERENCES users (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE entries
  OWNER TO app;

3 个答案:

答案 0 :(得分:1)

我的猜测是您的序列计数器需要重置(可能您已经在表中手动输入了数字而不是使用nextval,因此计数器没有增加)并且它会给出表中已有的数字。尝试用

之类的东西重新设置它
ALTER SEQUENCE my_seq RESTART 100000;

其中100000是一个大于的数字:

SELECT MAX(id) FROM entries;

答案 1 :(得分:0)

根据经验,如果你的dbms可以自动执行某些操作,你就不应该自己尝试。

CREATE TABLE entries
(
  -- bigserial provides automatic sequence numbers under
  -- dbms control.
  id bigserial NOT NULL,
  user_id bigint,
  CONSTRAINT entries_pkey PRIMARY KEY (id),
  CONSTRAINT fk_e3udjwux3ly7lu31huish0f82 FOREIGN KEY (user_id)
      REFERENCES users (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

插入此表而不参考&#34; id&#34;一点都不。

INSERT INTO ENTRIES (USER_ID) 
VALUES ('233'),('233');

或使用&#34;默认&#34;值。

INSERT INTO ENTRIES (ID, USER_ID) 
VALUES (default, '233'),(default, '233');

在此上下文中,默认不是字符串。 (没有引号。)

答案 2 :(得分:0)

代码是正确的,问题是序列的大小 - 它对于18k插入来说太小了。