Python Sqlite3: вставить в значение таблицы (словарь идет здесь)
Я хотел бы использовать словарь для вставки значений в таблицу, как бы я это сделал?
import sqlite3
db = sqlite3.connect('local.db')
cur = db.cursor()
cur.execute('DROP TABLE IF EXISTS Media')
cur.execute('''CREATE TABLE IF NOT EXISTS Media(
id INTEGER PRIMARY KEY, title TEXT,
type TEXT, genre TEXT,
onchapter INTEGER, chapters INTEGER,
status TEXT
)''')
values = {'title':'jack', 'type':None, 'genre':'Action', 'onchapter':None,'chapters':6,'status':'Ongoing'}
#What would I Replace x with to allow a
#dictionary to connect to the values?
cur.execute('INSERT INTO Media VALUES (NULL, x)'), values)
cur.execute('SELECT * FROM Media')
meida = cur.fetchone()
print meida
6 ответов
если вы пытаетесь использовать dict
чтобы указать имена столбцов и значения, вы не можете этого сделать, по крайней мере, напрямую.
это действительно присуще SQL. Если вы не укажете список имен столбцов, вы должны указать их в CREATE TABLE
порядок, который вы не можете сделать с dict
, потому что dict
не имеет никакого порядка. Если вы действительно хотите, конечно, вы можете использовать collections.OrderedDict
, убедитесь, что он в правильном порядке, а затем просто переходите values.values()
. Но почему бы и нет? просто имейте list
(или tuple
) в первую очередь? Если вы абсолютно уверены, что у вас есть все значения в правильном порядке, и вы хотите ссылаться на них по порядку, а не по имени, то у вас есть list
, а не dict
.
и нет способа связать имена столбцов(или имена таблиц и т. д.) в SQL просто значения.
вы можете, конечно, генерировать инструкцию SQL динамически. Например:
columns = ', '.join(values.keys())
placeholders = ', '.join('?' * len(values))
sql = 'INSERT INTO Media ({}) VALUES ({})'.format(columns, placeholders)
cur.execute(sql, values.values())
Впрочем, это почти всегда плохо идея. Это действительно не намного лучше, чем генерация и exec
Инг динамический код Python. И вы только что потеряли все преимущества использования заполнителей в первую очередь-в первую очередь защиту от атак SQL-инъекций, но и менее важные вещи, такие как более быстрая компиляция, лучшее кэширование и т. д. внутри DB engine.
вероятно, лучше отступить и посмотреть на эту проблему с более высокого уровня. Например, возможно, вам действительно не нужен статический список свойств, но а имя-значение MediaProperties
таблицы? Или, альтернативно, возможно, вам нужно какое-то документальное хранилище (будь то мощная система nosql или просто куча объектов JSON или YAML, хранящихся в shelve
)?
альтернативное использование именованные заполнители:
columns = ', '.join(my_dict.keys())
placeholders = ':'+', :'.join(my_dict.keys())
query = 'INSERT INTO my_table (%s) VALUES (%s)' % (columns, placeholders)
print query
cur.execute(query, my_dict)
con.commit()
есть решение для использования словарей. Во-первых, sql-оператор
INSERT INTO Media VALUES (NULL, 'x');
не будет работать, поскольку предполагается, что вы ссылаетесь на все столбцы в порядке, определенном в CREATE TABLE
заявление, как заявил абарнерт. (См.SQLite INSERT.)
после того, как вы исправили его, указав столбцы, вы можете использовать именованные заполнители для вставки данных. Преимущество этого заключается в том, что безопасно ускользает ключ-символы, так что вам не придется беспокоиться. От the Python sqlite-документация:
values = {'title':'jack', 'type':None, 'genre':'Action', 'onchapter':None,'chapters':6,'status':'Ongoing'}
cur.execute('INSERT INTO Media (id, title, type, onchapter, chapters, status) VALUES (:id, :title, :type, :onchapter, :chapters, :status);'), values)
можно использовать именованные параметры:
cur.execute('INSERT INTO Media VALUES (NULL, :title, :type, :genre, :onchapter, :chapters, :status)', values)
это еще зависит от порядка столбцов в INSERT
заявление (те :
используются только в качестве ключей в values
dict), но он, по крайней мере, уходит от необходимости упорядочивать значения на стороне python, плюс вы можете иметь другие вещи в values
которые здесь игнорируются; если вы тянете то, что в dict, чтобы сохранить его в нескольких таблицах, это может быть полезно.
если вы все еще хотите, чтобы избежать дублируя имена, вы можете извлечь их из sqlite3.Row
объект-результат, или cur.description
, после выполнения фиктивного запроса; может быть разумнее держать их в форме python рядом с тем, где вы делаете свой CREATE TABLE
.
key_lst = ('status', 'title', 'chapters', 'onchapter', 'genre', 'type')
cur.execute('INSERT INTO Media (status,title,chapters,onchapter,genre,type) VALUES ' +
'(?,?,?,?,?,?);)',tuple(values[k] for k in key_lst))
сделайте свой побег право.
вам, вероятно, также нужен commit
позвоните туда куда-нибудь.
У меня была аналогичная проблема, поэтому я сначала создал строку, а затем передал эту строку для выполнения команды. Это занимает больше времени, чтобы выполнить, но отображение было идеальным для меня. Просто работа вокруг:
create_string = "INSERT INTO datapath_rtg( Sr_no"
for key in record_tab:
create_string = create_string+ " ," + str(key)
create_string = create_string+ ") VALUES("+ str(Sr_no)
for key in record_tab:
create_string = create_string+ " ," + str(record_tab[key])
create_string = create_string + ")"
cursor.execute(create_string)
делая выше, я гарантировал, что если мой dict (record_tab) не содержит определенного поля, то скрипт не будет выбрасывать ошибку, и правильное сопоставление может быть сделано, поэтому я использовал словарь в первую очередь.
У меня была аналогичная проблема и закончилось чем - то не совсем похожим на следующее (примечание-это код OP с битами, измененными так, что он работает так, как они просили) -
import sqlite3
db = sqlite3.connect('local.db')
cur = db.cursor()
cur.execute('DROP TABLE IF EXISTS Media')
cur.execute('''CREATE TABLE IF NOT EXISTS Media(
id INTEGER PRIMARY KEY, title TEXT,
type TEXT, genre TEXT,
onchapter INTEGER, chapters INTEGER,
status TEXT
)''')
values = {'title':'jack', 'type':None, 'genre':'Action', 'onchapter':None,'chapters':6,'status':'Ongoing'}
#What would I Replace x with to allow a
#dictionary to connect to the values?
#cur.execute('INSERT INTO Media VALUES (NULL, x)'), values)
# Added code.
cur.execute('SELECT * FROM Media')
colnames = cur.description
list = [row[0] for row in cur.description]
new_list = [values[i] for i in list if i in values.keys()]
sql = "INSERT INTO Media VALUES ( NULL, "
qmarks = ', '.join('?' * len(values))
sql += qmarks + ")"
cur.execute(sql, new_list)
#db.commit() #<-Might be important.
cur.execute('SELECT * FROM Media')
media = cur.fetchone()
print (media)