Как преобразовать Python decimal в SQLite numeric?
У меня есть программа, которая считывает финансовые данные в JSON и вставляет их в базу данных SQLite. Проблема в том, когда я вставляю его в числовой столбец SQLite, и ему не нравится decimal
4 ответов
sqlite3
позволяет зарегистрировать адаптер (для прозрачного преобразования Decimals
to 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'>
по крайней мере, страница, на которую вы ссылались, не упоминала currency
тип данных, и decimal(10,5)
пример типа просто превращается в NUMERIC
сродство.
Если бы это были мои данные, я бы, вероятно, хранил целое число валютных "единиц" - пенни, или десятые части пенни, или сотые части Пенни, все, что подходит-а затем использовать коэффициент масштабирования чтобы превратить целочисленный вход в десятичный эквивалент для вычисления при чтении данных из база данных. Сложнее испортить целые числа.
Я обнаружил, что мне пришлось сделать небольшой твик для подхода 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", тогда этот столбец имеет сродство текста. Уведомление что тип VARCHAR содержит строку "CHAR" и, таким образом, назначен Сродство текста.
вы можете объявить столбцы любым типом, который вам нравится:
создать таблицу a_test( A_DECIMAL DECTEXT NOT NULL /* будет сохранен как текст */ );
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"),))
Не знаю, является ли это хорошим способом справиться с этим или нет - комментарии приветствуются