PostgreSQL的串行与MySQL的自动增量?

PostgreSQL的串行与MySQL的自动增量?,mysql,postgresql,auto-increment,postgresql-9.5,Mysql,Postgresql,Auto Increment,Postgresql 9.5,我有一段MySQL: CREATE TABLE seq_test ( id INT PRIMARY KEY AUTO_INCREMENT, name TEXT ); INSERT INTO seq_test(id, name) VALUES (1, 'one'); INSERT INTO seq_test(name) VALUES ('two'); 当我尝试在PostgreSQL中编写此代码时: CREATE TABLE seq_test ( id SERIAL PRIMARY

我有一段MySQL:

CREATE TABLE seq_test (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name TEXT
);

INSERT INTO seq_test(id, name) VALUES (1, 'one');
INSERT INTO seq_test(name) VALUES ('two');
当我尝试在PostgreSQL中编写此代码时:

CREATE TABLE seq_test (
  id SERIAL PRIMARY KEY,
  name TEXT
);

INSERT INTO seq_test(id, name) VALUES (1, 'one');
INSERT INTO seq_test(name) VALUES ('two');
我得到以下错误:

[23505] ERROR: duplicate key value violates unique constraint "seq_test_pkey"
  Detail: Key (id)=(1) already exists.
这是因为在PostgreSQL中,插入一个不会增加下一次插入的id。如何创建符合MySQL行为的表

这当然是一个人工示例,但我正在将一个大型代码库从MySQL移植到PostgreSQL,我无法控制的部分代码使用了两种样式,即带ID和不带ID,它们在MySQL中工作,但在PostgreSQL中不工作

一个丑陋的破解方法是总是选择setval'my_table_id_seq',从my_table中选择count*,真的…

没有不好的解决方案:要么坚持串行功能,要么自己处理

但你让我感兴趣,我想出了一个稍微不那么粗俗的解决办法,我希望是:创造一个触发器来完成所有肮脏的工作

触发函数 添加了通知,以便我们可以看到发生了什么:

CREATE OR REPLACE FUNCTION update_seq_val_seq_test()
  RETURNS TRIGGER AS $$
BEGIN
  RAISE NOTICE 'id is %', NEW.id;
  IF NEW.id > currval('seq_test_id_seq' :: REGCLASS)
  THEN
    RAISE NOTICE 'curval is %', currval('seq_test_id_seq' :: REGCLASS);
    PERFORM setval('seq_test_id_seq' :: REGCLASS, (NEW.id) :: BIGINT);
    RAISE NOTICE 'new curval is %', currval('seq_test_id_seq' :: REGCLASS); END IF;
  RETURN NULL;
END;
$$
LANGUAGE 'plpgsql' COST 1;
设置触发器 扣动扳机 快速脏测试

tests2=# insert into seq_test (name) values ('first');
NOTICE:  id is 30
INSERT 0 1
tests2=# select * from seq_test;
 id | name  
----+-------
 30 | first
(1 row)

tests2=# select currval('seq_test_id_seq'::regclass);
 currval 
---------
      30
(1 row)

tests2=# insert into seq_test (id, name) values (31, 'thirty one');
NOTICE:  id is 31
NOTICE:  curval is 30
NOTICE:  new curval is 31
INSERT 0 1
tests2=# select currval('seq_test_id_seq'::regclass);
 currval 
---------
      31
(1 row)

tests2=# select * from seq_test;
 id |    name    
----+------------
 30 | first
 31 | thirty one
(2 rows)

tests2=# insert into seq_test (name) values ('thirty dunno what');
NOTICE:  id is 32
INSERT 0 1
tests2=# insert into seq_test (id, name) values (21, 'back to the future');
NOTICE:  id is 21
INSERT 0 1
tests2=# select currval('seq_test_id_seq'::regclass);
 currval 
---------
      32
(1 row)

tests2=# select * from seq_test;
 id |        name        
----+--------------------
 30 | first
 31 | thirty one
 32 | thirty dunno what
 21 | back to the future
(4 rows)

tests2=# insert into seq_test (name) values ('thirty dunno what++');
NOTICE:  id is 33
INSERT 0 1
tests2=# select * from seq_test;
 id |        name         
----+---------------------
 30 | first
 31 | thirty one
 32 | thirty dunno what
 21 | back to the future
 33 | thirty dunno what++
(5 rows)

所以,现在Postgres更像你希望的那样处理这个案例,但是有很多事情需要为你检查:批量插入、回滚是如何工作的,这个触发器是如何影响性能的,对你来说还有更多的乐趣。

@muistoshort:不幸的是,对于提供ID的代码,我无能为力。不管怎样,撇开实用性不谈,在这种情况下,让PostgreSQL表现得像MySQL最简单的方法是什么?
tests2=# insert into seq_test (name) values ('first');
NOTICE:  id is 30
INSERT 0 1
tests2=# select * from seq_test;
 id | name  
----+-------
 30 | first
(1 row)

tests2=# select currval('seq_test_id_seq'::regclass);
 currval 
---------
      30
(1 row)

tests2=# insert into seq_test (id, name) values (31, 'thirty one');
NOTICE:  id is 31
NOTICE:  curval is 30
NOTICE:  new curval is 31
INSERT 0 1
tests2=# select currval('seq_test_id_seq'::regclass);
 currval 
---------
      31
(1 row)

tests2=# select * from seq_test;
 id |    name    
----+------------
 30 | first
 31 | thirty one
(2 rows)

tests2=# insert into seq_test (name) values ('thirty dunno what');
NOTICE:  id is 32
INSERT 0 1
tests2=# insert into seq_test (id, name) values (21, 'back to the future');
NOTICE:  id is 21
INSERT 0 1
tests2=# select currval('seq_test_id_seq'::regclass);
 currval 
---------
      32
(1 row)

tests2=# select * from seq_test;
 id |        name        
----+--------------------
 30 | first
 31 | thirty one
 32 | thirty dunno what
 21 | back to the future
(4 rows)

tests2=# insert into seq_test (name) values ('thirty dunno what++');
NOTICE:  id is 33
INSERT 0 1
tests2=# select * from seq_test;
 id |        name         
----+---------------------
 30 | first
 31 | thirty one
 32 | thirty dunno what
 21 | back to the future
 33 | thirty dunno what++
(5 rows)