2013-12-13 2 views
1

При создании небольшого приложения с использованием SQLite я заметил странную вещь (для меня) с поведением алгоритма счетчиков автоинкрементов.SQLite AUTOINCREMENT поведение счетчика столбцов с опцией ON CONFLICT IGNORE

Например, давайте попробуем создать базу данных с помощью следующей схемы

CREATE TABLE numbers (num INTEGER UNIQUE ON CONFLICT IGNORE); 

и небольшой Python скрипта

import sqlite3 

con = sqlite3.connect('db.sqlite3') 
cur = con.cursor() 

def values(): 
    for i in xrange(1, 3): 
     yield (i,) 
try: 
    cur.executemany('INSERT INTO numbers (num) VALUES (?)', values()) 
except sqlite3.DatabaseError, err: 
    print u'Error: ', err 
else: 
    con.commit() 
    print u'Number of added rows: %d' % cur.rowcount 

cur.close() 
con.close() 

Бежит сценарий три раза. Последний раз с разными значениями() вывода, например, xrange (3,5). Таким образом, мы получаем выход

Number of added rows: 2 
Number of added rows: 0 
Number of added rows: 2 

Хорошо, тогда давайте проверим нашу базу данных и все, кажется, как это должно

$ sqlite3 db.sqlite3 'select rowid, * from numbers' 
1|1 
2|2 
3|3 
4|4 

Затем попытайтесь создать базу данных с добавлением автоинкрементного псевдоним столбца системы RowId.

CREATE TABLE numbers (id INTEGER PRIMARY KEY AUTOINCREMENT, num INTEGER UNIQUE ON CONFLICT IGNORE); 

Затем выполните то же самое, что указано выше, и проверьте строки.

$ sqlite3 db.sqlite3 'select rowid, * from numbers' 
1|1|1 
2|2|2 
5|5|3 <- sqlite jumped over intermediate counter values for rowid and id column 
6|6|4 

SQLite сохраняет промежуточные значения счетчиков для ROWID и псевдоним столбца автоинкремента при использовании ИГНОРИРУЙТЕ ограничения алгоритм разрешения voilation для таблицы и пропускает их при назначении нового значения автоинкрементного. Зачем?

ответ

2

Потому что:

  1. SQLite видит, что ROWID не был указан и генерирует один. Для обычных INTEGER PRIMARY KEY случаев это в основном MAX(ROWID)+1. Для INTEGER PRIMARY KEY AUTOINCREMENT случаев новый номер, который никогда ранее не использовался, выбирается из специальной таблицы sqlite_sequence. В этой таблице приведены значения name и seq для идентификаторов строк автоинкремента.

  2. Втор. Уникальное ограничение нарушается, поэтому имеет место разрешение ON CONFLICT IGNORE. Эффективно ничего не сделано, и ошибка не возникает. Однако изменение sqlite_sequence по-прежнему было успешным и будет выполнено после завершения транзакции.

Ссылка: http://www.sqlite.org/autoinc.html

Смежные вопросы