вставить в таблицу sqlite с уникальным столбцом - PullRequest
7 голосов
/ 04 июня 2011

Я вставляю значения в свою таблицу (из кода Python) следующим образом:

cur.execute("insert into t(a, b, c) values (?, ?, ?)", (a, b, c))

В столбце c есть unique constraint.Каков обычный способ insert, если я хочу охватить случай, когда мы вставляем дублирующее значение для столбца c?
У меня есть несколько идей

  1. выбрать все от t до списка ипроверить перед вставкой, если значение уже присутствует
  2. блок try-catch
  3. более сложный оператор sqlite

Как бы вы его протестировали?

спасибо

Ответы [ 2 ]

13 голосов
/ 04 июня 2011

Вы можете использовать INSERT OR REPLACE , чтобы обновить строки с уникальным ограничением, или INSERT OR IGNORE , чтобы игнорировать вставки, конфликтующие с уникальным ограничением:

import sqlite3

def insert_or_replace():
    # https://sqlite.org/lang_insert.html
    connection=sqlite3.connect(':memory:')
    cursor=connection.cursor()
    cursor.execute('CREATE TABLE foo (bar INTEGER UNIQUE, baz INTEGER)')
    cursor.execute('INSERT INTO foo (bar,baz) VALUES (?, ?)',(1,2))
    cursor.execute('INSERT OR REPLACE INTO foo (bar,baz) VALUES (?, ?)',(1,3))
    cursor.execute('SELECT * from foo')
    data=cursor.fetchall()
    print(data)
    # [(1, 3)]


def on_conflict():
    # https://sqlite.org/lang_insert.html
    connection=sqlite3.connect(':memory:')
    cursor=connection.cursor()
    cursor.execute('CREATE TABLE foo (bar INTEGER UNIQUE, baz INTEGER)')
    cursor.execute('INSERT INTO foo (bar,baz) VALUES (?, ?)',(1,2))
    cursor.execute('INSERT OR IGNORE INTO foo (bar,baz) VALUES (?, ?)',(1,3))
    cursor.execute('SELECT * from foo')
    data=cursor.fetchall()
    print(data)
    # [(1, 2)]    

insert_or_replace()
on_conflict()

Эти команды sqlite, вероятно, быстрее, чем написание кода Python, чтобы сделать то же самое, хотя для проверки этого вы можете использовать модуль timeit Python для проверки скорости различных реализаций. Например, вы можете запустить

python -mtimeit -s'import test' 'test.insert_or_replace()'

против

python -mtimeit -s'import test' 'test.filter_nonunique_rows_in_Python()'

против

python -mtimeit -s'import test' 'test.insert_with_try_catch_blocks()'
1 голос
/ 04 июня 2011

Зависит от:)

Если есть только один вводчик, 1 может быть наиболее эффективным.

Если есть несколько вставок, которые вы должны использовать 2, как под 1, вы можете проверить и показаться ОК, но другой вставщик добавляет значение C, что у вас есть, поэтому он терпит неудачу

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...