Столбец не первичного ключа SQLite AUTOINCREMENT - PullRequest
0 голосов
/ 17 февраля 2019

У меня есть следующая таблица SQLite:

CREATE TABLE podcast_search (
        _id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
        search TEXT NOT NULL UNIQUE
)

Всякий раз, когда пользователь вставляет / обновляет строку в таблице, я хочу отсортировать эту строку в конце таблицы.Таким образом, если я вставлю следующие значения:

_id | search | sort
===================
  1 | foo    | 1
  2 | bar    | 2
  3 | quiz   | 3

, а затем обновлю строку 1 с foo до foo2, значения должны выглядеть следующим образом:

_id | search | sort
===================
  2 | bar    | 2
  3 | quiz   | 3
  1 | foo2   | 4

Я реализовал это таким образом:

CREATE TABLE podcast_search (
        _id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
        search TEXT NOT NULL UNIQUE, 
        update_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
CREATE TRIGGER update_date_update_trigger
    AFTER UPDATE ON podcast_search FOR EACH ROW
        BEGIN
            UPDATE podcast_search
                SET update_date = CURRENT_TIMESTAMP
                WHERE _id = OLD._id;
        END

Тем не менее, мои модульные тесты требуют 1000ms сна между операциями вставки / обновления для надежной сортировки, и эта величина задержки очень раздражает для модульного тестирования.

Я думал, что вместо этого мог бы реализовать векторные часы, но кажется, что значения AUTOINCREMENT существуют только для столбцов первичного ключа.SQLite предлагает какой-либо другой AUTOINCREMENT или AUTOINCREMENT -подобный вариант?

Я запускаю это на Android P, но это должно быть общей проблемой SQLite.

ОБНОВЛЕНИЕ

Сейчас я использую столбец sort INTEGER NOT NULL UNIQUE и SELECT - самую большую строку в этом столбце и вручную увеличиваю ее до значения INSERT/UPDATE:

CREATE TABLE podcast_search (
    _id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
    search TEXT NOT NULL UNIQUE,
    sort INTEGER NOT NULL UNIQUE
)

SELECT sort from podcast_search ORDER BY sort DESC

либо увеличьте sort в коде приложения, либо установите его на 0

Могу ли я сделать это вместо TRIGGER?

1 Ответ

0 голосов
/ 17 февраля 2019

Я думал, что вместо этого я мог бы реализовать векторные часы, но кажется, что значения AUTOINCREMENT существуют только для столбцов первичного ключа.Предоставляет ли SQLite какой-либо другой параметр AUTOINCREMENT или AUTOINCREMENT-подобный?

На самом деле они не являются значениями AUTOINCREMENT, а столбец с AUTOINCREMENT будет псевдонимом столбца rowid ;не потому, что AUTOINCREMENT был закодирован, а потому, что INTEGER PRIMARY KEY был закодирован.

Все, что делает AUTOINCREMENT при кодировании - это добавляет ограничение, что автоматически генерируемое значение ДОЛЖНО быть больше, чем любое другое существующее или используемое значение.Это становится очевидным, только если существует rowid со значением 9223372036854775807.В этом случае попытка вставить новую строку с автоматически сгенерированным rowid (т. Е. Для столбца rowid или его псевдонима не указано никакого значения) приведет к ошибке SQLITE_FULL.

Без AUTOINCREMENT и когда самый высокийrowid равен 9223372036854775807 (максимально возможное значение для rowid). Предпринята попытка использовать свободное значение, которое, очевидно, будет меньше, чем 9223372036854775807. Автоинкремент SQLite

  • Возможно, вы захотите отметить самую первую строку связанной страницы, которая гласит: -

  • Ключевое слово AUTOINCREMENT накладывает дополнительные ресурсы ЦП, памяти, дискового пространства и дискового ввода-вывода.и следует избегать, если не строго необходимо.Обычно это не нужно.

  • Я не вижу необходимости в вашем описании.

Итак, вам нужно назначить значение для столбца, который должен быть отсортирован, на 1 больше, чем максимальное текущее значение для этого столбца, так что оно становится самым последним для целей сортировки, подзапрос, который извлекает max(the_column) + 1, сделаетчто ты хочешь.Это может быть UPDATE, TRIGGER или INSERT.

  • rowid = max(rowid) + 1 - это, в основном, то, как SQLite присваивает значение rowid, если только AUTOINCREMENT не используется, когда 1 добавляется к наибольшему из max (rowid) и значение для соответствующей таблицы, полученное из таблицы sqlite_sequence (будет существовать, только если используется AUTOINCREMENT).Начисление и поддержание sqlite_sequence влечет за собой штрафы.

Например, вы можете использовать следующее (что устраняет необходимость в дополнительном столбце и дополнительном индексе): -

-- SETUP THE DATA FOR TESTING
DROP TABLE IF EXISTS podcast_searchv1;

CREATE TABLE IF NOT EXISTS podcast_searchv1 (
        _id INTEGER NOT NULL PRIMARY KEY, 
        search TEXT NOT NULL UNIQUE
);

INSERT INTO podcast_searchv1 (search) 
VALUES('foo'),('bar'),('guide')
;

-- Show original data
SELECT * FROM podcast_searchv1;

-- DO THE UPDATE
UPDATE podcast_searchv1 SET search = 'new value', _id = (SELECT max(_id) + 1 FROM podcast_searchv1) WHERE search = 'foo';

-- Show the changed data
SELECT * FROM podcast_searchv1;

Результаты: -

enter image description here

, а затем: -

enter image description here

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