如何从表中选择 *,但使用 ORM (Sqlalchemy) 将一个或多个列转换为不同的数据类型

问题描述 投票:0回答:1

我有一个用于 fastapi 端点的多 orm 模型,如下所示:

@mapper_registry.mapped
@dataclass
class Department:
    __tablename__ = "department"
     __sa_dataclass_metadata_key__ = "sa"

    id: float = field(
        init=False, metadata={"sa": Column(NUMBER(15, 0, False), primary_key=True)})
    label: str = field(metadata={"sa": Column(VARCHAR(255), nullable=False)})
    active: str = field(
        metadata={"sa": Column(CHAR(1), nullable=False, server_default=text("'Y' "))})
    sort_order: Optional[float] = field(
        default=None, metadata={"sa": Column(NUMBER(4, 0, False))})
    entry_key: Optional[str] = field(
        default=None, metadata={"sa": Column(VARCHAR(255))})
    external_key: Optional[str] = field(
        default=None, metadata={"sa": Column(VARCHAR(255), server_default=text("null"))})
  date_created: datetime = field(metadata={"sa": Column(TIMESTAMP(True), nullable=False)})
 date_modified: datetime = field(metadata={"sa": Column(TIMESTAMP(True), nullable=False)})

还有 pydantic 模型等价物。

from pydantic import BaseModel
class DepartmentResponse(BaseModel):
    id: float
    label: str
    active: str
    date_created: datetime
    date_modified: datetime

我正在使用 python oracledb。最初的问题是,在这种情况下,获取带有时区的时间戳(date_modified 和 date_created)会引发错误 ORA-01805:日期/时间操作中可能出现错误 https://github.com/oracle/python-oracledb/issues/20 。该错误与带有时区的 oracle 时间戳的内部实现有关。

基本上,我正在尝试探索在获取之前将 date_created 和 date_modified 转换为字符串的解决方法。 举例来说:

Select COLUMN1, COLUMN3... COLUMN N, CAST(COLUMN2 as INT)

这只是一个简单的例子。我有带有嵌套对象(表)和大量列的表,所以我不想一一调用它们只是为了解决这个时间戳获取问题,并且我试图尽可能避免多个连接语句(主要我首先使用 sqlalchemy/orm 的原因)

也许我的问题应该是在通过重置字段来获取这些时间戳之前,使用时区字段来预制这些时间戳。在获取期间将时间戳转换为字符串 (func.to_char) 适用于时间戳字段。

或者很大程度上是解决时间戳获取错误的一种方法。

oracle sqlalchemy orm fastapi python-oracledb
1个回答
0
投票

基本上,我正在尝试探索在获取之前将 date_created 和 date_modified 转换为字符串的解决方法。举例来说:

Select COLUMN1, COLUMN3... COLUMN N, CAST(COLUMN2 as INT)

您需要了解,当您使用 ORM 时,大多数情况下是 ORM 编写查询。这实际上是主要卖点之一。要实现您所描述的目标,您需要

  1. 避免将

    COLUMN2
    本身映射到其表的模型类。当然,这意味着您无法通过 ORM 设置该列的值,但如果您依赖数据库中的触发器来维护相关列,那应该没问题。

  2. 假设您需要该列的数据,请指示您的 ORM 将表达式

    CAST(COLUMN2 as INT)
    映射到模型类实例的属性。

由于您使用的是 SQLAlchemy 的声明性映射样式,因此您应该只获得您声明的映射,因此 (1) 应该很容易。

SQLAlchemy 的文档虽然数量庞大,但对于如何完成 (2) 的实现有点不透明,但可能是通过使用

column_property()
代替
Column()
/
mapped_column()
来实现。您甚至可以将 SQL 表达式指定为纯 Python 字符串,例如:

  date_created: int = column_property('CAST(date_created as INT)')

但是,我不明白你在问题中显示的任何内容如何与......

我有带有嵌套对象(表)和大量列的表,所以我不想一一调用它们只是为了解决这个时间戳获取问题

您绝对需要(至少)单独映射您想要在 Python 端交互的每一列,并且您显示的映射示例似乎表明您已经认识到并正在尝试这样做。

© www.soinside.com 2019 - 2024. All rights reserved.