nextval(seq_name)没有从数据库中获取正确的值



我有一个flask与sqlalchemy绑定到postgres数据库。所有组件都在读取功能齐全的情况下工作。我有一个简单的模型:

class School(db.Model):
    __tablename__ = 'schools'
    id = db.Column(db.Integer, db.Sequence('schools_id_seq'), primary_key=True)
    name = db.Column(db.String(80))
    active = db.Column(db.Boolean)
    created = db.Column(db.DateTime)
    updated = db.Column(db.DateTime)
    def __init__(self, name, active, created, updated):
        self.name = name
        self.active = active
        self.created = created
        self.updated = updated

正在处理一个postgres表:

CREATE SEQUENCE schools_id_seq;
CREATE TABLE schools(
  id  int   PRIMARY KEY NOT NULL DEFAULT nextval('schools_id_seq'),
  name  varchar(80) NOT NULL,
  active boolean DEFAULT TRUE,
  created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER SEQUENCE schools_id_seq OWNED BY schools.id;

当我从psql中对这个表进行插入时,一切正常:

cake=# select nextval('schools_id_seq');
 nextval 
---------
      65
(1 row)
cake=# INSERT INTO schools (id, name, active, created, updated) VALUES (nextval('schools_id_seq'),'Test', True, current_timestamp, current_timestamp);
INSERT 0 1

导致:

66 | Test                           |          0 | t      | 2016-08-25 14:12:24.928456 | 2016-08-25 14:12:24.928456

但是当我尝试从flask中插入相同的插入时,堆栈跟踪抱怨重复的id,但它使用nextval来获得该值:

sqlalchemy.exc。(psycopg2.IntegrityError)重复键值违反唯一约束"schools_pkey"DETAIL: Key (id)=(7)已经存在。[SQL: "INSERT INTO schools (id, name, active, created, updated) VALUES (nextval('schools_id_seq'), %(name)s, %(active)s, %(created)s, %(updated)s)返回学校。][参数:{'active': True, 'name': ' testong ', 'updated': datetime. id"][参数:{'active': True, 'name': ' testong ', 'updated':日期时间。]Datetime (2016, 8, 25, 14, 10, 5, 703471), 'created': Datetime。Datetime (2016, 8,25,14,10,5,703458)}]

为什么对nextval的sqlalchemy调用不返回与postgres db中相同调用产生的相同的下一个val ?

更新:@RazerM告诉我关于echo=true参数,我不知道。

app.config['SQLALCHEMY_ECHO']=True

我从一个新的插入中产生(注意,在这个尝试中它获取了10,应该是67):

2016-08-25 14:47:40,127 INFO sqlalchemy.engine.base.Engine select version()
2016-08-25 14:47:40,128 INFO sqlalchemy.engine.base.Engine {}
2016-08-25 14:47:40,314 INFO sqlalchemy.engine.base.Engine select current_schema()
2016-08-25 14:47:40,315 INFO sqlalchemy.engine.base.Engine {}
2016-08-25 14:47:40,499 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2016-08-25 14:47:40,499 INFO sqlalchemy.engine.base.Engine {}
2016-08-25 14:47:40,594 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2016-08-25 14:47:40,594 INFO sqlalchemy.engine.base.Engine {}
2016-08-25 14:47:40,780 INFO sqlalchemy.engine.base.Engine show standard_conforming_strings
2016-08-25 14:47:40,780 INFO sqlalchemy.engine.base.Engine {}
2016-08-25 14:47:40,969 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2016-08-25 14:47:40,971 INFO sqlalchemy.engine.base.Engine INSERT INTO schools (id, name, active, created, updated) VALUES (nextval('schools_id_seq'), %(name)s, %(active)s, %(created)s, %(updated)s) RETURNING schools.id
2016-08-25 14:47:40,971 INFO sqlalchemy.engine.base.Engine {'name': 'Testing', 'created': datetime.datetime(2016, 8, 25, 14, 47, 38, 785031), 'active': True, 'updated': datetime.datetime(2016, 8, 25, 14, 47, 38, 785050)}
2016-08-25 14:47:41,064 INFO sqlalchemy.engine.base.Engine ROLLBACK

sqlalchemy.exc。(psycopg2.IntegrityError)重复键值违反唯一约束"schools_pkey"DETAIL: Key (id)=(10)已经存在。[SQL: "INSERT INTO schools (id, name, active, created, updated) VALUES (nextval('schools_id_seq'), %(name)s, %(active)s, %(created)s, %(updated)s)返回学校。]Id "][参数:{'updated':日期时间。]Datetime (2016, 8, 25, 14, 54, 18, 262873), 'created':日期时间。datetime(2016,8,25,14,54,18,262864), 'active': True, 'name': 'Testing'}]

在这种情况下,解决方案很简单,它没有解释为什么,因为我认为我们应该看整个环境,你不能给我们看,否则会花费太长时间。因此,尝试插入尽可能多的记录,因为它将达到67,并且下一次插入应该没有任何错误,因为序列最小值将达到适当的值。当然,您可以尝试先将server_default选项添加到id属性:

 server_default=db.Sequence('schools_id_seq').next_value()

seq = db.Sequence('schools_id_seq')

在class中:

id = db.Column(db.Integer, seq, server_default=seq.next_value(), primary_key=True)

Sqlalchemy以这样的方式提到:

Sequence最初是打算首先作为python端指令的,所以以这种方式指定它可能是一个好主意。

序列总是递增的,因此select语句和SQLAlchemy都对值递增。

如序列操作函数中所述:

将序列对象推进到下一个值并返回该值。这是自动完成的:即使多个会话并发执行nextval,每个会话也会安全地接收到不同的序列值。

如果使用默认参数创建了序列对象,则连续的nextval调用将返回以1开头的连续值。其他行为可以通过在CREATE SEQUENCE命令中使用特殊参数获得;有关更多信息,请参阅其命令参考页。

重要提示:为了避免阻塞从相同序列获取数字的并发事务,nextval操作永远不会回滚;也就是说,一旦获取了一个值,就认为它已被使用,不会再次返回。即使周围的事务后来终止,或者调用查询最终没有使用该值,也是如此。例如,带有ON CONFLICT子句的INSERT将计算要插入的元组,包括执行任何所需的nextval调用,然后再检测导致它遵循ON CONFLICT规则的任何冲突。这种情况会留下未使用的"漏洞"。在赋值序列中。因此,PostgreSQL序列对象不能用于获取"gapless"序列。

相关内容

  • 没有找到相关文章

最新更新