【问题标题】:very long integers in SQLAlchemy with SQLite带有 SQLite 的 SQLAlchemy 中的非常长的整数
【发布时间】:2021-09-25 18:48:33
【问题描述】:

我在使用 sqlite db 的 sqlalchemy 中处理非常长的整数(例如 2100000000000000000000)。错误:“Python int 太大,无法转换为 SQLite INTEGER”。

stackoverflow 中的答案建议改用字符串,但我考虑使用数字(比例=0)。使用数字有什么缺点吗?

from sqlalchemy import create_engine, MetaData, Table, Integer, Column, String, Numeric

meta_sl = MetaData()
engine = create_engine('sqlite:///testint.db')
conn_sl = engine.connect()

example = Table('example', meta_sl,
                Column('id', Integer, primary_key=True),
                Column('int', Integer),
                Column('str', String),
                Column('num', Numeric(scale=0)))

meta_sl.create_all(engine)

ins = example.insert()
my_int = 2100000000000000000000
try:
    conn_sl.execute(ins, {"id": 2,
                          "int": my_int,  # causes error!
                          "str": str(my_int),  # workaround nr.1
                          "num": my_int})  # workaround nr.2
except OverflowError:
    conn_sl.execute(ins, {"id": 2,
                          "str": str(my_int),  # workaround nr.1
                          "num": my_int})  # workaround nr.2

【问题讨论】:

    标签: python sqlite sqlalchemy integer-overflow


    【解决方案1】:

    使用数字有什么缺点吗?

    是的,因为它并不总是有效。

    SQLite documentation中所述:

    如果 TEXT 值是格式正确的整数文字,它太大而无法放入 64 位有符号整数,则将其转换为 REAL。对于 TEXT 和 REAL 存储类之间的转换,仅保留数字的前 15 位有效十进制数字。

    所以在你的特殊情况下,使用Numeric(scale=0) 似乎没问题……

    ins = example.insert()
    my_int = 2100000000000000000000
    with engine.begin() as conn_sl:
        conn_sl.execute(
            ins,
            {
                "id": 2,
                # "int": my_int,  # causes error!
                "str": str(my_int),  # workaround nr.1
                "num": my_int,  # workaround nr.2
            },
        )
    with engine.begin() as conn_sl:
        result = conn_sl.execute(sa.select(example.c.num)).fetchall()
        print(result)
        # [(Decimal('2100000000000000000000'),)]
    

    ...但 SQLAlchemy 也警告说

    方言 sqlite+pysqlite 原生支持 Decimal 对象,并且 SQLAlchemy 必须从浮点转换 - 可能会出现舍入错误和其他问题。请考虑在此平台上将十进制数存储为字符串或整数,以实现无损存储。

    例如,如果我们使用my_int = 1234567890123456789012,它会以Decimal('1234567890123456774144') 进行往返。

    【讨论】:

      猜你喜欢
      • 2014-02-02
      • 1970-01-01
      • 2021-01-16
      • 1970-01-01
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      相关资源
      最近更新 更多