SQLAlchemy:如何在一个事务中交换唯一值?
SQLAlchemy: how exchange unique values in one transaction?
我的版本:
$ python
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.0.0'
让我们看一下 sqlite 的示例(在生产中我使用 mysql,但这里并不重要):
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column
from sqlalchemy import create_engine
from sqlalchemy import Integer, String
Base=declarative_base()
engine = create_engine('sqlite:///:memory:', echo=True)
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(16))
tech_id = Column(Integer, unique=True, nullable=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
s = Session()
现在我们添加两条记录:
u1=User(name="User1", tech_id=None)
u2=User(name="User2", tech_id=10)
s.add(u1)
s.add(u2)
s.commit()
接下来尝试修改它们:
u1=s.query(User).filter(User.name=="User1").first()
u2=s.query(User).filter(User.name=="User2").first()
u2.tech_id=None
u1.tech_id=10
s.commit()
提交后出现异常:
<-- cut -->
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: user.tech_id [SQL: 'UPDATE user SET tech_id=? WHERE user.id = ?'] [parameters: ((10, 1), (None, 2))]
如果我这样做:
u2.tech_id=None
s.commit()
u1.tech_id=10
s.commit()
没关系。
是否可以仅通过一次提交(仅通过一次事务)进行请求?
你可以这样做:
#u1=s.query(User).filter(User.name=="User1").first()
#u2=s.query(User).filter(User.name=="User2").first()
#u2.tech_id=None
#u1.tech_id=10
#s.commit()
s.query(User).filter(User.name=="User2").update(
{User.tech_id: None}
)
s.query(User).filter(User.name=="User1").update(
{User.tech_id: 10}
)
s.commit()
更改的本质是执行正确的操作顺序。即使在提交之前,您也不能为唯一键(至少在 mysql 中)创建重复值。但是您可以为唯一列创建多个 NULL 值。
我的版本:
$ python
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.0.0'
让我们看一下 sqlite 的示例(在生产中我使用 mysql,但这里并不重要):
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column
from sqlalchemy import create_engine
from sqlalchemy import Integer, String
Base=declarative_base()
engine = create_engine('sqlite:///:memory:', echo=True)
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(16))
tech_id = Column(Integer, unique=True, nullable=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
s = Session()
现在我们添加两条记录:
u1=User(name="User1", tech_id=None)
u2=User(name="User2", tech_id=10)
s.add(u1)
s.add(u2)
s.commit()
接下来尝试修改它们:
u1=s.query(User).filter(User.name=="User1").first()
u2=s.query(User).filter(User.name=="User2").first()
u2.tech_id=None
u1.tech_id=10
s.commit()
提交后出现异常:
<-- cut -->
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: user.tech_id [SQL: 'UPDATE user SET tech_id=? WHERE user.id = ?'] [parameters: ((10, 1), (None, 2))]
如果我这样做:
u2.tech_id=None
s.commit()
u1.tech_id=10
s.commit()
没关系。
是否可以仅通过一次提交(仅通过一次事务)进行请求?
你可以这样做:
#u1=s.query(User).filter(User.name=="User1").first()
#u2=s.query(User).filter(User.name=="User2").first()
#u2.tech_id=None
#u1.tech_id=10
#s.commit()
s.query(User).filter(User.name=="User2").update(
{User.tech_id: None}
)
s.query(User).filter(User.name=="User1").update(
{User.tech_id: 10}
)
s.commit()
更改的本质是执行正确的操作顺序。即使在提交之前,您也不能为唯一键(至少在 mysql 中)创建重复值。但是您可以为唯一列创建多个 NULL 值。