Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在多主键表中插入具有自动增量id的行?_Python_Sql_Database_Sqlalchemy - Fatal编程技术网

Python 如何在多主键表中插入具有自动增量id的行?

Python 如何在多主键表中插入具有自动增量id的行?,python,sql,database,sqlalchemy,Python,Sql,Database,Sqlalchemy,我正在写一个turbogears2应用程序。我有一张这样的桌子: class Order(DeclarativeBase): __tablename__ = 'order' # id of order id = Column(Integer, autoincrement=True, primary_key=True) # buyer's id buyer_id = Column(Integer, ForeignKey('user.user_id',

我正在写一个turbogears2应用程序。我有一张这样的桌子:

class Order(DeclarativeBase):
    __tablename__ = 'order'

    # id of order
    id = Column(Integer, autoincrement=True, primary_key=True)

    # buyer's id
    buyer_id = Column(Integer, ForeignKey('user.user_id',
        onupdate="CASCADE", ondelete="CASCADE"), primary_key=True)
我想在此表中插入新行,但得到的字段“order\u id”没有默认值错误。似乎我必须手动设置订单的id,因为我有两个主键。我的问题是,如何插入自动生成新ID的行

如果我手动生成id,我会遇到一些问题。例如:

maxId = DBSession.query(func.max(Order)).one()[0]
newOrder = Order(id=maxId + 1, buyer_id=xxx)
DBSession.add(newOrder)
以这种方式添加一个新订单似乎是可以的,但是,如果两个请求几乎同时运行这些代码,我们就会遇到一些问题

如果有请求a和b,请按以下顺序运行此代码:

a.maxId = DBSession.query(func.max(Order)).one()[0]
b.maxId = DBSession.query(func.max(Order)).one()[0]
b.newOrder = Order(id=maxId + 1, buyer_id=xxx)
b.DBSession.add(newOrder)
a.newOrder = Order(id=maxId + 1, buyer_id=xxx)
a.DBSession.add(newOrder)
然后请求a可能失败,因为表中已经有一个具有相同id的订单。我可以捕获异常并重试。但我想知道,有没有更好的办法

有时,id不是简单的整数,我们可能需要这样的订单id:

class Order(DeclarativeBase):
    __tablename__ = 'order'

    # id of order
    id = Column(Integer, autoincrement=True, primary_key=True)

    # buyer's id
    buyer_id = Column(Integer, ForeignKey('user.user_id',
        onupdate="CASCADE", ondelete="CASCADE"), primary_key=True)
2009年9月1日第33次订单的20090133标准


在这种情况下,“自动增量”不可用。所以我别无选择,手动为订单分配id。所以我的另一个问题是,除了捕获异常并重试插入id为的行之外,还有什么更好的方法吗?

如果您希望订单中每个买家都有序列号,那么您必须将插入到一个买家的事务序列化。您可以通过在买方行上获取独占锁来实现这一点:

sess.query(Buyer.id).with_lockmode('update').get(xxx)
order_id = sess.query(func.max(Order.id)+1).filter_by(buyer_id=xxx).scalar() or 1
sess.add(Order(id=order_id, buyer_id=xxx))

当两个交易试图并行插入一个买家的订单时,使用此模式,其中一个交易将在第一行阻塞,直到另一个交易完成或失败。

您应该在列定义中使用默认值

id = Column(Integer, default = sqlexpression)
其中sqlexpression可以是sql表达式。这是你的电话号码。对于自动增量,应使用sql表达式coalesceselect maxorder.id from order,0+1。为了方便起见,您可以导入sqlalchemy.sql.text,以便id列看起来像

id = Column(Integer, default = text("coalesce(select max(order.id) from order,0) + 1"))