我如何让 Flask-SQLAlchemy 与 Postgres 一起,让主键不重复使用已删除的号码?



我正在使用Flask-SQLAlchemy和Postgres。我注意到,当我删除一条记录时,下一条记录将重复使用该记录的 ID,这不适合我的目的。另一个SO问题是这是默认行为。特别是,他的SO问题讨论了幕后的sql。但是,当我测试此问题的解决方案时,它不起作用。事实上,postgres 并没有使用SERIAL作为主键。我不得不自己pgadmin编辑它。其他程序中的解决方案提到使用Sequence但没有显示序列的来源。

所以我希望这段代码:


class Test1(db.Model):
__tablename__ = "test1"
# id = ... this is what needs to change
id = db.Column(db.Integer, primary_key=True)

如果删除记录 3 并像这样创建另一个记录 3,则不会重用说 3:

i1 = Invoice()
db.session.add(i1)
i2 = Invoice()
db.session.add(i2)
i3 = Invoice()
db.session.add(i3)
db.session.commit()
invs = Invoice.query.all()
for i in invs:
print(i.id)  # Should print 1,2,3
Invoice.query.filter(id=3).delete()  # no 3 now
db.session.commit()
i4 = Invoice()
db.session.add(i4)
db.session.commit()
invs = Invoice.query.all()
for i in invs:
print(i.id)  # Should print 1,2,4

其他,据说使用autoincrement=False的解决方案。好的,但是我如何确定要设置 id 的数字是什么?有没有办法将变量保存在类中而不将其保存为列:

class Test2(db.Model)
__tablename__ = 'test2'
id = ...
last_id = 3
# code to set last_id when a record is deleted

编辑: 所以我可以(虽然我认为我不应该(使用Python来做到这一点。我认为这更清楚地试图说明我正在努力做的事情。

class Test1(db.Model):
__tablename__ = "test1"
# id = ... this is what needs to change
id = db.Column(db.Integer, primary_key=True) 
last_used_id = 30
def __init__(self):
self.id = last_used_id + 1
self.last_used_id +=1
# Not sure if this somehow messes with SQLAlchemy / the db making the id first.

这将使任何新记录不触及已使用的 ID。 但是,通过这种方法,我确实遇到了 Python 的类变量问题行为。看到这个SO问题


未来的自检:在此处查看 UUID 每条@net评论:

你应该使用autoincrement=True.这将在您每次添加新行时自动递增 id。

class Test1(db.Model):
__tablename__ = "test1"
id = db.Column(db.Integer, primary_key=True, autoincrement=True, unique=True, nullable=False)
....

默认情况下,由于性能问题,Postgres 不会重用 id。试图避免间隙或重复使用已删除的 ID 会产生可怕的性能问题。请参阅 PostgreSQL wiki FAQ。

您无需跟踪 ID。当您调用db.session.add(i4)db.session.commit()时,它将自动插入递增的 id。

最新更新