3

我的主要目标是使实施修订历史和日记更容易。

我发现自己想知道是否有可能使用 Flask-SQLAlchemy(或直接使用 SQL)来为 mysql 获取自动递增的非唯一整数。 我发现这个堆栈溢出帖子与我想要做的很接近,但问题集中在主键上。例如,如果我的表有这些列,

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 的问题?

这个系统的优点是它使发布历史(和差异)非常简单。每当有人想修改帖子时,我都会使用与原始帖子相同的 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。

4

1 回答 1

5

引用一条经典的 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。

于 2013-08-12T21:59:01.393 回答