在 sqlite3 中使用十进制和金钱与适配器时出现问题



使用 sqlite3 作为数据库,我想保留几个小数。十进制值,一个是百分比,另一个是美元金额。 但是,在超过 20,000 个条目上使用 sum(amount) 时,我遇到了问题。 差了几块钱。

我想使用适配器来节省美分的数量,然后聚合应该可以工作。

sqlite3.register_adapter(decimal.Decimal, lambda x:str(x))
sqlite3.register_adapter(decimal.Decimal, lambda x:int(x*100))

但是,我现在需要两个类,因为我不能使用相同的类。 尝试对十进制进行子类化成为一个问题,因为它本身使用十进制。 好。 我将复制 decimal.py 并将十进制|十进制的每个出现替换为 Money|money。

$ 复制 decimal.py money.py$ sed -e "s/Decimal/Money/g" -e "s/decimal/money/g" -i money.py$ money.py

所有单元测试都有效。 我现在尝试一下,但收到"可能不支持的类型"错误。 我改变转换器,使用基本类型。 我只是无法让它正常工作,我对这个问题没有更好的想法。

我需要一些帮助,并在下面有一个示例。 关于如何使其工作或使用标准库的更好解决方案的想法?

import decimal
import money
import sqlite3
sqlite3.register_adapter(decimal.Decimal, lambda x:str(x))
sqlite3.register_converter('decimal', decimal.Decimal)
sqlite3.register_adapter(money.Money, lambda x: int(value*100))
sqlite3.register_converter('intcents', lambda x: money.Money(x)/100)
conn = sqlite3.connect(":memory:",
        detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
cursor = conn.cursor()
cursor.executescript("CREATE TABLE example(rate decimal, amount intcents)")
for x in (1,1,1,2,2,2,3,3,3):
    rate = decimal.Decimal(str(x))/100
    amount = money.Money(str(rate))
    try:
        cursor.execute("INSERT INTO example VALUES(?,?)", (rate, amount))
    except:
        print (rate, amount)
        raise
cursor.execute("""SELECT sum(rate), sum(amount) FROM example""")
print cursor.fetchone()
cursor.execute("""SELECT sum(rate) as "t [decimal]", sum(amount)as "a [intcents]"FROM example""")
print cursor.fetchone()

有两个简单的解决方案,我希望有人有更直接的东西:
1. 转换为字符串并将字符串存储在数据库中
2.乘以100并存储为货币值
的整数这两者都需要转换回十进制。从数据库读取值时为小数。

问题出在register_adapter。 奇怪的是,它没有导致给我一个名称错误。 另一种解决方案需要在每个输入和输出上进行处理。 这将否定register_adapter和register_converter的原因。通过注释中的语法修复,它运行良好。

最新更新