如何将Python十进制转换为SQLite数字?
我有一个程序可以读取 JSON 格式的财务数据并将其插入到 SQLite 数据库中。问题是当我将它插入 SQLite 数字列时,它似乎不喜欢 十进制 对象。
我发现这个问题之前回答过,但答案已经过时并且来自我的理解 SQLite 现在有一种货币数据类型称为数字。
现在作为一种解决方法,我将十进制值存储为文本,但是是否可以将其存储为数字?对于数据库插入和财务计算,我是否受困于将小数转换为字符串(反之亦然)的开销?
I have a program that reads financial data in JSON and inserts it into an SQLite database. The problem is when I'm inserting it into SQLite numeric column and it doesn't seem to like the decimal object.
I've found this question answered before, but the answer is outdated and from what I understand SQLite now has a currency data type called numeric.
Right now as a workaround I'm storing decimal values as text, but is it possible to store it as numeric? Am I stuck with the overhead of converting decimals to strings and vice versa for database inserts and financial calculations?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
sqlite3
允许您注册一个适配器(在插入时透明地将Decimals
转换为TEXT
)和一个转换器(以透明地转换TEXT<获取时将 /code> 转换为
小数
)。以下是来自 文档的示例代码的轻微修改版本:
产量
sqlite3
allows you to register an adapter (to transparently convertDecimals
toTEXT
when inserting) and a converter (to transparently convertTEXT
intoDecimals
when fetching).The following is a lightly modified version of the example code from the docs:
yields
SQLite 的列亲和性规则说:
您可以将列声明为您喜欢的任何类型:
不知道这是否是处理它的好方法 - 欢迎评论
The column affinity rules for SQLite say:
You can declare columns to be any type you like:
Don't know if this is a good way to handle it or not - comments welcome
我发现我必须对 unutbu 的方法进行一些小调整。对于值为“4.00”的修改示例,它从数据库中返回为“4”。我正在处理商品,不想将精度硬编码到数据库中(就像我只是乘以 100 并除以 100 时所做的那样)。因此,我对转换函数进行了如下调整:
这在美观上并不好,但确实挫败了 sqlite 将字段存储为整数的渴望,并失去了精度的跟踪。
I found that I had to make a small tweak to unutbu's approach. With a modified example with a value '4.00', it comes back out of the database as '4'. I'm dealing with commodities and don't want to hardcode the precision into the database (like I'd be doing if I just multiplied and divided by 100). So I tweaked the conversion functions as follows:
which isn't aesthetically great but does defeat sqlite's eagerness to store the field as an integer and lose track of the precision.
至少您链接到的页面没有提及
currency
数据类型,并且decimal(10,5)
示例数据类型 只需打开NUMERIC
亲和性。如果是我的数据,我可能会存储整数个货币“单位”——便士,或十分之一便士,或百分之一便士,任何合适的——然后使用缩放因子< /em> 将整数输入转换为十进制,相当于从数据库读取数据时进行计算。搞砸整数就更难了。
At least the page you linked to didn't mention a
currency
data type, and thedecimal(10,5)
example datatype simply turns on theNUMERIC
affinity.If it were my data, I'd probably store an integer number of currency "units" -- pennies, or tenths of a penny, or hundredths of a penny, whatever is appropriate -- and then use a scaling factor to turn the integer input into the decimal equivalent to compute with when reading data from the database. It's harder to screw up with integers.
我基本上遵循与其他人相同的方法,但有一点补充。问题是定义适配器和转换器会处理逐行访问十进制列的情况。但是,当您发出聚合函数时,例如对所有行的小数列求和,求和是使用实数(即浮点算术)完成的,并且返回的结果将是带有后续舍入误差的浮点数。
解决方案是创建一个定制的聚合函数,decimal_sum。由于sqlite3聚合函数受到它们可能返回的类型的限制,decimal_sum将返回十进制总和的字符串表示形式,这将是Decimal< /em> 类型(此代码也兼容 Python 3):
打印:
I am basically following the same approach as others but with one addition. The problem is that defining an adapter and converter takes care of the case of when you are accessing decimal columns row by row. But when you issue an aggregate function, such as summing a decimal column across all rows, the summation is done using real (i.e. floating point arithmetic) and the returned result will be a float with subsequent rounding errors.
The solution is to create a custom-tailored aggregate function, decimal_sum. Since sqlite3 aggregate functions are constrained in the types that they may return, decimal_sum will return a string representation of the decimal sum, which will be case to a Decimal type (this code is also Python 3-compatible):
Prints: