首页 文章

Postgres中多次插入序列失败

提问于
浏览
0

有一个插入查询具有多个值(大约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

    我的猜测是你的序列计数器需要重置(也许你已经在表中手动输入了数字而不是使用nextval,因此计数器没有增加)并且它给出了你已经在表中的数字 . 尝试用类似的东西重置它

    ALTER SEQUENCE my_seq RESTART 100000;
    

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

    SELECT MAX(id) FROM entries;
    
  • 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
    );
    

    插入此表而不引用“id” .

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

    或使用“默认”值 .

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

    在此上下文中,default不是字符串 . (没有引号 . )

  • 1

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

相关问题