0

用例

我将 SQLAlchemy 和 SQLite 用于独立应用程序(非 Web),我需要将数值范围存储在数据库中。我通过在 SQLite 中保存每个范围的开始和结束来做到这一点,如下所示:

[[float("-inf"), 0], [1, 1000],..., [9999, 12000], [12001, float("inf")]]

在最终的应用程序中,我需要确定任意值number落在哪个范围内。我正在做如下的事情:

...
for range_ in ranges:
    range_start, range_end = range_
    if range_start <= number <= range_end:
        return range_
...

number可以是任何整数或无穷大,因此 db 中的范围必须从负无穷大延伸到正无穷大

问题

以下代码工作正常

import sqlalchemy as sa
from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session


Base = declarative_base()


class MyMappedClass(Base):
    __tablename__ = "my_table"
    id = sa.Column(sa.Integer, primary_key=True)
    ranges = sa.Column(sa.JSON)


if __name__ == "__main__":
    engine = sa.create_engine("sqlite://", future=True)
    Session = scoped_session(sessionmaker(bind=engine))

    session = Session()
    Base.metadata.create_all(session.bind)
    mapped_class = MyMappedClass(
        ranges=[[float("-inf"), 1], [1, float("inf")]],
    )
    with session:
        session.add(mapped_class)
        session.commit()

但是当我添加一个CheckConstraint调用时,json_array_length(ranges)我得到一个malformed JSON错误:

...
ranges = sa.Column(
    sa.JSON,
    sa.CheckConstraint("json_array_length(ranges) >= 2"),
)
...

追溯:

...
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) malformed JSON
...

我确认[[float("-inf"), 1], [1, float("inf")]]没有通过更改CheckConstraintto将其转换为有效的 JSON,json_valid(ranges)并且仅当列中存在无穷大时它才会失败。

必须能够将CheckConstraints 添加到ranges列中。我需要对其他列执行数据验证步骤。其中的细节很复杂,超出了这个问题的范围。

解决方法

我想我可以通过这样替换来解决这个float("inf")问题"inf"

mapped_class = MyMappedClass(
    ranges=[["-inf", 1], [1, "inf"]],
)

我可以确定任意的范围,number例如:

...
for range_ in ranges:
    range_start, range_end = range
    if float(range_start) <= number <= float(range_end):
        return range_
...

但现在我在列中混合了类型,我更喜欢只存在数字。

回到问题

有没有办法在 JSON1 列中存储无穷大?如果有其他数据库支持数组中的无穷大(适用于独立应用程序),请分享。理想情况下,SQLAlchemy 支持这个数据库。

4

0 回答 0