如何使用SQLalchemist创建自动生成的价值?

发布于 2025-02-11 02:18:29 字数 2093 浏览 0 评论 0原文

我正在尝试使用SQLalchemist创建DB,以与Snowflake和Alembic连接到FastApi创建的应用程序的迁移。我创建了一些模型,所有模型都可以在雪花上创建这个模型以示例:

create or replace TABLE PRICE_SERVICE.FP7.LOCATION (
    ID NUMBER(38,0) NOT NULL autoincrement,
    CREATED_AT TIMESTAMP_NTZ(9),
    UPDATED_AT TIMESTAMP_NTZ(9),
    ADDRESS VARCHAR(16777216),
    LATITUDE VARCHAR(16777216) NOT NULL,
    LONGITUDE VARCHAR(16777216) NOT NULL,
    unique (LATITUDE),
    unique (LONGITUDE),
    primary key (ID)
);

但是当我尝试为此表创建一个新的OBJ时,我得到了:

sqlalchemy.orm.exc.FlushError: Instance <Location at 0x7fead79677c0> has a NULL identity key.  If this is an auto-generated value, check that the database table allows generation of new primary key values, and that the mapped Column object is configured to expect these generated values.  Ensure also that this flush() is not occurring at an inappropriate time, such as within a load() event.

我的模型是:

class Location(Base):
    id = Column(Integer, primary_key=True)
    address = Column(String)
    latitude = Column(String, unique=True, nullable=False)
    longitude = Column(String, unique=True, nullable=False)

    buildings = relationship("Building", back_populates="location")
    quotes = relationship("Quote", back_populates="location")
    binds = relationship("Bind", back_populates="location")

而且我正在尝试这样做:

def create_location(db: Session, data: Dict[str, Any]) -> Location:
    location = Location(
        address=data["address"],  # type: ignore
        latitude=data["lat"],  # type: ignore
        longitude=data["lng"],  # type: ignore
    )
    db.add(location)
    db.commit()
    
    return location

我也是我。尝试使用:

id = Column(Integer, Sequence("id_seq"), primary_key=True)

但是我得到了:

 sqlalchemy.exc.StatementError: (sqlalchemy.exc.ProgrammingError) (snowflake.connector.errors.ProgrammingError) 000904 (42000): SQL compilation error: error line 1 at position 7
backend_1  | invalid identifier 'ID_SEQ.NEXTVAL'

I'm trying to create a db using sqlalchemist to connect with snowflake and alembic to migrations for an app created in FastAPI. I created some models and all works fine to create this one in snowflake for examples:

create or replace TABLE PRICE_SERVICE.FP7.LOCATION (
    ID NUMBER(38,0) NOT NULL autoincrement,
    CREATED_AT TIMESTAMP_NTZ(9),
    UPDATED_AT TIMESTAMP_NTZ(9),
    ADDRESS VARCHAR(16777216),
    LATITUDE VARCHAR(16777216) NOT NULL,
    LONGITUDE VARCHAR(16777216) NOT NULL,
    unique (LATITUDE),
    unique (LONGITUDE),
    primary key (ID)
);

but when I try to create a new obj to this table and I'm getting:

sqlalchemy.orm.exc.FlushError: Instance <Location at 0x7fead79677c0> has a NULL identity key.  If this is an auto-generated value, check that the database table allows generation of new primary key values, and that the mapped Column object is configured to expect these generated values.  Ensure also that this flush() is not occurring at an inappropriate time, such as within a load() event.

my model is:

class Location(Base):
    id = Column(Integer, primary_key=True)
    address = Column(String)
    latitude = Column(String, unique=True, nullable=False)
    longitude = Column(String, unique=True, nullable=False)

    buildings = relationship("Building", back_populates="location")
    quotes = relationship("Quote", back_populates="location")
    binds = relationship("Bind", back_populates="location")

and I'm trying to do this:

def create_location(db: Session, data: Dict[str, Any]) -> Location:
    location = Location(
        address=data["address"],  # type: ignore
        latitude=data["lat"],  # type: ignore
        longitude=data["lng"],  # type: ignore
    )
    db.add(location)
    db.commit()
    
    return location

also I tried using:

id = Column(Integer, Sequence("id_seq"), primary_key=True)

but I got:

 sqlalchemy.exc.StatementError: (sqlalchemy.exc.ProgrammingError) (snowflake.connector.errors.ProgrammingError) 000904 (42000): SQL compilation error: error line 1 at position 7
backend_1  | invalid identifier 'ID_SEQ.NEXTVAL'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如梦亦如幻 2025-02-18 02:18:29

您忘了在模型中定义序列。当您定义雪花中表创建的序列值时,序列将在架构级别生成。

from sqlalchemy import Column, Integer, Sequence
...


class Location(Base):
    id = Column(Integer, Sequence("Location_Id"), primary_key=True, 
        autoincrement=True)
    address = Column(String)
...

确保您的用户角色具有使用该顺序的权限,并且应该照顾您的问题,为您的主键设置下一个值。

一种可以帮助我使用表主键的方法是定义一个使用dectrared_attr自动根据表名称定义我的主键的Mixin类。

from sqlalchemy import Column, Integer, Sequence
from slqalchemy.ext.declarative import declared_attr


class SomeMixin(object):
    @declared_attr
    def record_id(cls):
        """
        Use table name to define pk
        """"
        return Column(
            f"{cls.__tablename__} Id",
            Integer(),
            primary_key=True, 
            autoincrement=True
        )

然后,您将所述mixin传递到您的模型中

from sqlalchemy import Column, Integer, String, Sequence
from wherever import SomeMixin

class Location(Base, SomeMixin):
    address = Column(String)
    ...

location.record_id通过您在混音中定义的序列设置。

希望这有所帮助

You forgot to define the Sequence in your model. When you define the Sequence value on table creation in Snowflake a Sequence is generated at the schema level.

from sqlalchemy import Column, Integer, Sequence
...


class Location(Base):
    id = Column(Integer, Sequence("Location_Id"), primary_key=True, 
        autoincrement=True)
    address = Column(String)
...

Make sure your user role has usage permission for that sequence and that should take care of your issue setting the next value for your primary key.

An approach that helps me with table primary keys is defining a mixin class that uses declared_attr to automatically define my primary keys based on the table name.

from sqlalchemy import Column, Integer, Sequence
from slqalchemy.ext.declarative import declared_attr


class SomeMixin(object):
    @declared_attr
    def record_id(cls):
        """
        Use table name to define pk
        """"
        return Column(
            f"{cls.__tablename__} Id",
            Integer(),
            primary_key=True, 
            autoincrement=True
        )

Then you pass said mixin into your model

from sqlalchemy import Column, Integer, String, Sequence
from wherever import SomeMixin

class Location(Base, SomeMixin):
    address = Column(String)
    ...

Now Location.record_id gets set through the sequence you defined in the mixin.

Hope this helped

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文