使用SQLAlchemy在创建时自动递增非唯一ID

时间:2013-08-12 21:49:36

标签: mysql sqlalchemy flask-sqlalchemy

我的主要目标是更轻松地实施修订历史记录和日记功能。

我发现自己想知道是否有可能使用Flask-SQLAlchemy(或直接使用SQL)来获取mysql的自动递增非唯一整数。 I found this stack overflow post which is close to what I want to do but the question is focused on a primary key.例如,如果我的表有这些列,

revision_id = db.Column(db.Integer, nullable=False)
post_id = db.Column(db.Integer, nullable=False)

__table_args__ = (
    PrimaryKeyConstraint('post_id', 'revision_id'),
)

是否可以创建一个新的帖子,其中revision_id为1,post_id为max(post_id)+ 1,而没有两个用户同时尝试创建帖子并创建相同的post_id的问题?< / p>

这个系统的优势在于它使后期历史(和差异)变得非常简单。每当有人想要修改帖子时我都会使用与原文相同的post_id并增加revision_id(现在我输入的内容有同样的问题)。

更新

Sylvain Leroux 让我走上正确的道路,如何解决我的问题。我需要将两个表都设置为sqlalchemy中的主键。如果sqlalchemy中有多个主键,则不会认为它们是唯一的。这是我目前的定义,

revision_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=False, default=1)
post_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
__table_args__ = (
    PrimaryKeyConstraint('post_id', 'revision_id'),
)

哪个产生这个SQL

CREATE TABLE `post` (
    revision_id INTEGER NOT NULL, 
    post_id INTEGER NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (post_id, revision_id), 
)

允许我在有和没有post_id的情况下插入。

所有归功于 Sylvain Leroux 因为我只是将他的答案翻译成SQLAlchemy。

1 个答案:

答案 0 :(得分:4)

引用经典的MySQL错误消息:

  

只能有一个自动列,必须将其定义为键:

auto_increment列必须是(in)主键或(in)键(在MySQL中也称为索引,可能是也可能是唯一的)。


至于:

SELECT MAX(id) FROM tbl INTO @new_id;
INSERT INTO tbl (id, ...) VALUES (@new_id, ....);

您清楚地知道,如果两个并发请求执行相同的操作,您将最终拥有两个完全不相关的新行,并且具有相同的ID。你可能不想使用表锁来避免这个陷阱。

就我自己而言,我会说“不要那样做”。也许这会让你的应用程序中的某些事情变得更容易,但我敢打赌,这会使的其他东西更复杂或很多不那么健壮


但是......如果真正的问题是如何保持“post id”不变,请记住auto_increment可以是 的一个键(http://sqlfiddle.com/#!2/9b4b45/1):

create table tbl(id int auto_increment not null, 
                 rev int not null default 1,
                 content TEXT,
                 primary key(id,rev));

-- insert 3 new contents with "auto id" and default revision 1
insert into tbl (content) values ("alpha"), ("bta"), ("gamma");

假设项目id2,rev1中存在错误。您可以插入新版本:

insert into tbl (id, rev, content) values (2,2,"beta");

如果您想查看项目ID2的各种修订:

select * from tbl where id=2 order by rev;

你必须找到如何使用SQLAlchemy(:D)来做到这一点,但这绝对可以通过MySQL实现。