问题描述
|
我有一个程序,可以读取JSON中的财务数据并将其插入到sqlite数据库中。问题是当我将其插入sqlite数字列时,它似乎不喜欢小数对象。
我已经找到了之前回答过的问题,但是答案已经过时了,据我了解,sqlite现在具有一种称为数字的货币数据类型。
现在,作为一种解决方法,我将十进制值存储为文本,但是可以将其存储为数字吗?对于数据库插入和财务计算,我是否会承受将小数转换为字符串,反之亦然的开销?
解决方法
sqlite3
可让您注册一个适配器(在插入时将Decimals
转换为TEXT
)和一个转换器(在获取时将TEXT
转换为Decimals
)。
以下是来自文档的示例代码的略微修改版本:
import sqlite3
import decimal
D=decimal.Decimal
def adapt_decimal(d):
return str(d)
def convert_decimal(s):
return D(s)
# Register the adapter
sqlite3.register_adapter(D,adapt_decimal)
# Register the converter
sqlite3.register_converter(\"decimal\",convert_decimal)
d = D(\'4.12\')
con = sqlite3.connect(\":memory:\",detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.cursor()
cur.execute(\"create table test(d decimal)\")
cur.execute(\"insert into test(d) values (?)\",(d,))
cur.execute(\"select d from test\")
data=cur.fetchone()[0]
print(data)
print(type(data))
cur.close()
con.close()
产量
4.12
<class \'decimal.Decimal\'>
, 我发现我必须对unutbu的方法进行一些小的调整。对于一个修改后的示例,其值为\'4.00 \',它从数据库中以\'4 \'的形式返回。我正在处理商品,并且不想将精度硬编码到数据库中(就像我只是乘以100并除以整数一样)。因此,我对转换函数进行了如下调整:
def adapt_decimal(d):
return \'#\'+str(d)
def convert_decimal(s):
return D(s[1:])
虽然从美学上讲不是很好,但确实打败了sqlite渴望将字段存储为整数并失去精度的渴望。
, http://www.sqlite.org/datatype3.html#affinity
如果列的声明类型包含任何字符串
\“ CHAR \”,\“ CLOB \”或\“ TEXT \”,则该列具有TEXT关联性。注意
VARCHAR类型包含字符串\“ CHAR \”并因此被分配
TEXT关联。
您可以将列声明为您喜欢的任何类型:
创建表a_test(
a_decimal DECTEXT NOT NULL / *将存储为TEXT * /
);
def adapt_decimal(d):
return str(d)
def convert_decimal(s):
return decimal.Decimal(s)
# Register the adapter
sqlite3.register_adapter(decimal.Decimal,adapt_decimal)
# Register the converter
sqlite3.register_converter(\"DECTEXT\",convert_decimal)
con = sqlite3.connect(\"test.s3db\",detect_types=sqlite3.PARSE_DECLTYPES)
C1 = con.cursor()
C1.execute(\"INSERT INTO a_test VALUES(?)\",(decimal.Decimal(\"102.20\"),))
不知道这是否是处理它的好方法-欢迎发表评论
, 至少您链接到的页面没有提到currency
数据类型,而decimal(10,5)
示例数据类型只是打开了NUMERIC
相似性。
如果是我的数据,我可能会存储整数形式的货币“单位”-几美分或十分之一便士,或百分之一便士,如果合适的话-然后使用比例因子从数据库读取数据时,将整数输入转换为十进制等效值以进行计算。用整数搞砸比较困难。