У меня есть набор данных, хранящийся локально в базе данных sqlite3. Я извлек столбец, выполнил некоторые операции и теперь хочу заменить ВСЕ значения в столбце базы данных. Как я могу это сделать?

Длина столбца и списка гарантированно будет одинаковой. Я просто хочу обновить таблицу новыми значениями. Есть ли простой способ сделать это сразу?

Использование python 2.7

Отредактировано, чтобы добавить:

MyList - это серия панд, поддерживаемая массивом numpy dtype 'object'. Столбец таблицы myCol имеет текстовый формат.

In [1]: curr.execute('UPDATE test SET myCol= ?', myList)

---------------------------------------------------------------------------
ProgrammingError                          Traceback (most recent call last)
f:\python\<ipython-input-52-ea41c426502a> in <module>()
----> 1 curr.execute('UPDATE test SET myCol = ?', myList)

ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 401125 supplied.
5
Zelazny7 28 Мар 2013 в 21:33

1 ответ

Лучший ответ

Вместо этого используйте метод .executemany():

curr.executemany('UPDATE test SET myCol= ?', myList)

Однако здесь myList должен быть последовательностью кортежей. Если это не так, для создания этих кортежей подойдет выражение генератора:

curr.executemany('UPDATE test SET myCol= ?', ((val,) for val in myList))

Демонстрация (с прошивками):

>>> import sqlite3
>>> conn=sqlite3.connect(':memory:')
>>> conn.execute('CREATE TABLE test (myCol)')
<sqlite3.Cursor object at 0x10542f1f0>
>>> conn.commit()
>>> myList = ('foo', 'bar', 'spam')
>>> conn.executemany('INSERT into test values (?)', ((val,) for val in myList))
<sqlite3.Cursor object at 0x10542f180>
>>> list(conn.execute('select * from test'))
[(u'foo',), (u'bar',), (u'spam',)]

Обратите внимание, что для оператора UPDATE вы должны иметь оператор WHERE для определения строки для обновления. UPDATE без фильтра WHERE обновит все строки.

Убедитесь, что ваши данные имеют идентификатор строки. в этом случае может быть проще использовать именованные параметры:

my_data = ({id=1, value='foo'}, {id=2, value='bar'})
cursor.executemany('UPDATE test SET myCol=:value WHERE rowId=:id', my_data)
8
Martijn Pieters 28 Мар 2013 в 21:53
Кажется, это обновляет ВСЕ значения myCol с каждым значением, найденным в myList. Конечным результатом является то, что каждая строка обновленного столбца имеет последнее значение, найденное в myList. Я хочу: row1 = myList[0], row2=myList[1] и т. Д.
 – 
Zelazny7
28 Мар 2013 в 21:49
1
@ Zelazny7: Нет, executemany() выполняет итерацию по myList и эффективно вызывает execute() для каждой записи. Однако для этого требуется, чтобы каждая запись myList была кортежем.
 – 
Martijn Pieters
28 Мар 2013 в 21:52
@ Zelazny7: А, я вижу проблему. У вас нет пункта нет WHERE. Как вы ожидаете, что база данных узнает, что myCol принадлежит какой строке?
 – 
Martijn Pieters
28 Мар 2013 в 21:54
1
Но в том-то и дело. Я хочу сделать прямую замену всего столбца. Я мало (ничего) знаю о том, как хранятся строки. Возможно, я наивно предполагал, что они находятся в том же порядке, в котором хранились? Я использую эту базу данных только как внешнее хранилище для таблицы данных. Количество рядов ВСЕГДА будет одинаковым.
 – 
Zelazny7
28 Мар 2013 в 21:58
1
@ Zelazny7: Даже если ваша схема SQLite не включает явный идентификатор, есть внутренний идентификатор строки, который вы также можете выбрать. См. sqlite.org/autoinc.html. Вам нужно явно запросить для него при получении данных, и вам нужно использовать тот же идентификатор при использовании UPDATE для повторного сопоставления строк.
 – 
Martijn Pieters
28 Мар 2013 в 22:02