You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLAlchemy默认值重复问题:如何让UUID列每次生成新值?

问题:SQLAlchemy中UUID默认值重复,如何实现每次插入自动生成新UUID?

在SQLAlchemy的declarative_base子类中定义了一个默认值为uuid4的列,但运行脚本时,每次插入的UUID都会沿用同一个值。需要实现每次插入数据时自动生成新的UUID作为该列的默认值。

错误代码示例

import os
import uuid
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base


Base = declarative_base()

class Test(Base):
    __tablename__ = "test"
    id = Column(Integer, autoincrement=True, primary_key=True)
    msg = Column(String(100), nullable=False)
    # 错误:类定义时就执行了uuid.uuid4().hex,生成固定值
    uuid = Column(String(32), default=uuid.uuid4().hex, nullable=True)


engine = create_engine(
    os.getenv('SQLALCHEMY_DATABASE_URI'),
    echo=True
)
Session = sessionmaker(bind=engine)

for x in range(2):
    model = Test(msg=f"Hey! - {x}")
    with Session() as session:
        session.add(model)
        session.commit()
        session.close()

实际输出(Echo日志)

2022-10-10 14:42:44,963 INFO sqlalchemy.engine.Engine SELECT CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR)
2022-10-10 14:42:44,963 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-10-10 14:42:45,005 INFO sqlalchemy.engine.Engine SELECT schema_name()
2022-10-10 14:42:45,005 INFO sqlalchemy.engine.Engine [generated in 0.00022s] ()
2022-10-10 14:42:45,081 INFO sqlalchemy.engine.Engine SELECT CAST('test max support' AS NVARCHAR(max))
2022-10-10 14:42:45,081 INFO sqlalchemy.engine.Engine [generated in 0.00032s] ()
2022-10-10 14:42:45,202 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-10-10 14:42:45,204 INFO sqlalchemy.engine.Engine INSERT INTO test (msg, uuid) OUTPUT inserted.id VALUES (?, ?)
2022-10-10 14:42:45,204 INFO sqlalchemy.engine.Engine [generated in 0.00020s] ('Hey! - 0', '58a2f6d418a9428b92c0b81ad81c4585')
2022-10-10 14:42:45,311 INFO sqlalchemy.engine.Engine COMMIT
2022-10-10 14:42:45,371 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-10-10 14:42:45,371 INFO sqlalchemy.engine.Engine INSERT INTO test (msg, uuid) OUTPUT inserted.id VALUES (?, ?)
2022-10-10 14:42:45,371 INFO sqlalchemy.engine.Engine [cached since 0.1675s ago] ('Hey! - 1', '58a2f6d418a9428b92c0b81ad81c4585')
2022-10-10 14:42:45,478 INFO sqlalchemy.engine.Engine COMMIT

期望输出(Echo日志)

2022-10-10 14:56:18,458 INFO sqlalchemy.engine.Engine SELECT CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR)
2022-10-10 14:56:18,458 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-10-10 14:56:18,518 INFO sqlalchemy.engine.Engine SELECT schema_name()
2022-10-10 14:56:18,519 INFO sqlalchemy.engine.Engine [generated in 0.00022s] ()
2022-10-10 14:56:18,599 INFO sqlalchemy.engine.Engine SELECT CAST('test max support' AS NVARCHAR(max))
2022-10-10 14:56:18,599 INFO sqlalchemy.engine.Engine [generated in 0.00018s] ()
2022-10-10 14:56:18,704 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-10-10 14:56:18,706 INFO sqlalchemy.engine.Engine INSERT INTO test (msg, uuid) OUTPUT inserted.id VALUES (?, ?)
2022-10-10 14:56:18,706 INFO sqlalchemy.engine.Engine [generated in 0.00019s] ('Hey! - 0', '58a2f6d418a9428b92c0b81ad81c4585')
2022-10-10 14:56:18,846 INFO sqlalchemy.engine.Engine COMMIT
2022-10-10 14:56:18,862 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-10-10 14:56:18,862 INFO sqlalchemy.engine.Engine INSERT INTO test (msg, uuid) OUTPUT inserted.id VALUES (?, ?)
2022-10-10 14:56:18,863 INFO sqlalchemy.engine.Engine [cached since 0.1569s ago] ('Hey! - 1', '13f37ce5a48c44bbaa0c883f2f35da3d')
2022-10-10 14:56:18,929 INFO sqlalchemy.engine.Engine COMMIT

解决方案

问题原因

代码中default=uuid.uuid4().hex是在类定义阶段就执行了uuid.uuid4().hex,生成了一个固定的字符串,之后所有创建的Test实例都会复用这个固定值,导致UUID重复。

SQLAlchemy的default参数需要接收可调用对象(比如函数或lambda),而不是直接传递函数执行的结果,这样每次创建实例时才会调用该对象生成新值。

修改后的代码

将UUID列的default值改为lambda函数,每次创建实例时都会调用该lambda生成新的UUID hex字符串:

import os
import uuid
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base


Base = declarative_base()

class Test(Base):
    __tablename__ = "test"
    id = Column(Integer, autoincrement=True, primary_key=True)
    msg = Column(String(100), nullable=False)
    # 正确:传递lambda函数,每次创建实例时执行生成新的UUID hex
    uuid = Column(String(32), default=lambda: uuid.uuid4().hex, nullable=True)


engine = create_engine(
    os.getenv('SQLALCHEMY_DATABASE_URI'),
    echo=True
)
Session = sessionmaker(bind=engine)

for x in range(2):
    model = Test(msg=f"Hey! - {x}")
    with Session() as session:
        session.add(model)
        session.commit()
        session.close()

另一种实现方式

如果希望将UUID的生成逻辑封装成独立函数,也可以直接传递函数名(注意不要加括号,否则会立即执行):

def generate_uuid():
    return uuid.uuid4().hex

# 在列定义中使用:
uuid = Column(String(32), default=generate_uuid, nullable=True)

这样每次创建Test实例时,SQLAlchemy都会调用generate_uuid()生成新的UUID值,满足需求。


内容的提问来源于stack exchange,提问作者MertG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 04:32:09