Complete worked example
python
from sqlalchemy import create_engine, select, String
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Role(Base):
__tablename__ = "roles"
id: Mapped[int] = mapped_column(primary_key=True)
code: Mapped[str] = mapped_column(String(50), unique=True)
def inspect_example(codes):
engine = create_engine("sqlite+pysqlite://", connect_args={"autocommit": False})
try:
Base.metadata.create_all(engine)
duplicates = 0
with Session(engine) as session, session.begin():
session.add(Role(code="seed"))
session.flush()
for code in codes:
try:
with session.begin_nested():
session.add(Role(code=code))
session.flush()
except IntegrityError:
duplicates += 1
with Session(engine) as check:
stored = list(check.scalars(select(Role.code).order_by(Role.code)))
return {"codes": stored, "duplicates": duplicates}
finally:
engine.dispose()- Reasoning
- The program flushes the seed before processing candidates. For each candidate it enters begin_nested, adds the Role and flushes inside that context. IntegrityError is caught outside the nested block so the savepoint context can roll back its failed insert before processing continues. SQLAlchemy flushes pending work when begin_nested starts, even if ordinary autoflush is disabled. This is why the seed’s boundary is explicit. For candidates [seed, a, a, b], the final codes are [a, b, seed] with two duplicate attempts, not an empty table or a partially inactive Session.