带有 SQLite 的 SQLAlchemy 中的非常长的整数

very long integers in SQLAlchemy with SQLite

我在使用 sqlite 数据库的 sqlalchemy 中遇到非常长的整数(例如 2100000000000000000000)。错误:“Python int 太大而无法转换为 SQLite INTEGER”。

Whosebug 中的答案建议改用字符串,但我考虑使用数字 (scale=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

Are there any disadvantages using numeric?

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

SQLite documentation 中所述:

If the TEXT value is a well-formed integer literal that is too large to fit in a 64-bit signed integer, it is converted to REAL. For conversions between TEXT and REAL storage classes, only the first 15 significant decimal digits of the number are preserved.

所以在您的特定情况下,使用 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 还警告说

Dialect sqlite+pysqlite does not support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.

例如,如果我们使用 my_int = 1234567890123456789012,它的往返行程为 Decimal('1234567890123456774144')