使用适配器在sqlite3中使用小数和金钱的问题

时间:2011-05-18 15:25:51

标签: python sqlite decimal currency

使用sqlite3作为数据库,我想保留几个decimal.Decimal值,一个百分比另一个美元金额。但是我在超过20,000个条目上使用sum(金额)时遇到了问题。这是几美元。

我想过使用适配器来节省分数,然后聚合应该有效。

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

但是,我现在需要两个类,因为我不能使用同一个类。试图将Decimal子类化成一个问题因为它本身使用了Decimal。精细。我只需复制decimal.py并用Money | money替换每个Decimal | decimal的出现。

$ copy 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()

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

问题出在register_adapter中。奇怪的是,它没有给我一个NameError。另一种解决方案需要在每个输入和输出处进行处理。这将否定register_adapter和register_converter的原因。通过注释中的语法修复,它可以很好地工作。