带有 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')
。
我在使用 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')
。