SQLite вставляет или игнорирует и возвращает исходный _rowid_

Я потратил некоторое время на чтение документации SQLite, различные вопросы и ответы здесь, на Stack Overflow, и эта вещь , но не пришли к полному ответу.

Я знаю, что нет никакого способа сделать что-то вроде INSERT OR IGNORE INTO foo VALUES(...) с SQLite и возвратить rowid исходной строки, а ближайший к нему будет INSERT OR REPLACE но это удалит весь строка и вставляет новую строку и, таким образом, получает новый rowid .

Пример таблицы:

 CREATE TABLE foo( id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT ); 

Сейчас я могу сделать:

 sql = sqlite3.connect(":memory:") # create database sql.execute("INSERT OR IGNORE INTO foo(data) VALUES(?);", ("Some text.", )) the_id_of_the_row = None for row in sql.execute("SELECT id FROM foo WHERE data = ?", ("Some text.", )): the_id_of_the_row = row[0] 

Но что-то идеальное выглядело бы так:

 the_id_of_the_row = sql.execute("INSERT OR IGNORE foo(data) VALUES(?)", ("Some text", )).lastrowid 

Какой лучший (прочитанный: самый эффективный) способ вставить строку в таблицу и вернуть rowid или игнорировать строку, если она уже существует, и просто получить rowid? Эффективность важна, потому что это будет происходить довольно часто.

Есть ли способ INSERT OR IGNORE и вернуть rowid строки, с которой сравнивалась проигнорированная строка? Это было бы здорово, так как это было бы так же эффективно, как вставка.

2 Solutions collect form web for “SQLite вставляет или игнорирует и возвращает исходный _rowid_”

Способ, который работал лучше всего для меня, заключался в том, чтобы insert or ignore значения, и select rowid двумя разными шагами. Я использовал unique ограничение для столбца data чтобы ускорить выбор и избежать дубликатов.

 sql.execute("INSERT OR IGNORE INTO foo(data) VALUES(?);" ("Some text.", )) last_row_id = sql.execute("SELECT id FROM foo WHERE data = ?;" ("Some text. ", )) 

Операция select не так медленна, как я думал. Это, похоже , связано с тем, что SQLite автоматически создает индекс для unique столбцов.

INSERT OR IGNORE – это ситуации, в которых вам не нужна личность записи; где цель состоит только в том, чтобы иметь некоторую запись с этим конкретным значением.

Если вы хотите узнать, вставлена ​​ли новая запись или нет, вам нужно проверить вручную:

 the_id_of_the_row = None for row in sql.execute("SELECT id FROM foo WHERE data = ?", ...): the_id_of_the_row = row[0] if the_id_of_the_row is None: c = sql.cursor() c.execute("INSERT INTO foo(data) VALUES(?)", ...) the_id_of_the_row = c.lastrowid 

Что касается эффективности: когда SQLite проверяет столбец data для дубликатов, он должен выполнять точно такой же запрос, который вы делаете с SELECT , и как только вы это сделали, путь доступа находится в кеше, поэтому производительность не должна быть проблемой. В любом случае необходимо выполнить два отдельных запроса INSERT / SELECT (в любом порядке, как ваш, так и мой код работает, но ваш проще).

  • Выберите и обновите в той же транзакции с помощью python sqlite
  • почему я не смог построить sqlite3 при сборке python?
  • Как увеличить время ожидания соединения с помощью sqlalchemy с sqlite в python
  • Проблема с заменой параметра SQLite
  • Как я могу ссылаться на столбцы по их именам в python, вызывающем SQLite?
  • Ошибка Sqlite load_extension для пространственных объектов в Python
  • Различия Datetime в Django с использованием SQLite
  • Как вычесть значения из двух разных таблиц sqlite3 в python
  • Python - лучший язык программирования в мире.