Уникальное поле QLDB
Я хочу создать уникальное поле в QLDB. Я пытался использоватьUNIQUE
, но получите:
unexpected token found, KEYWORD : unique; Unexpected token following CREATE
2 ответа
Согласно справочнику QLDB PartiQL,
Amazon QLDB поддерживает не все операции PartiQL.
И CREATE TABLE
справочные документы говорят,
QLDB поддерживает открытый контент и не применяет схему, поэтому вы не определяете атрибуты или типы данных при создании таблиц. [курсив мой]
Следовательно, логичный вывод - QLDB не поддерживает UNIQUE
ограничения на любые поля, которые вы определяете в своей таблице.
Это подтверждено учебником QLDB.
Оператор INSERT создает начальную редакцию документа с нулевым номером версии. Чтобы однозначно идентифицировать каждый документ,QLDB назначает идентификатор документа как часть метаданных.
Важный
Поскольку QLDB не применяет схему, вы можете вставить один и тот же документ в таблицу несколько раз. Каждый оператор вставки фиксирует отдельную запись документа в журнале, а QLDB присваивает каждому документу уникальный идентификатор.
Единственное поле, уникальность которого гарантируется QLDB, - этоdocumentId
.
Редактировать:
Вы можете обеспечить уникальность своего приложения. Вот как:
- Начать транзакцию
- Выполнить
SELECT id FROM myTable By id WHERE myUniqueField = ?
- Определите, существует ли уже запись для этого значения
myUniqueField
- Вставьте новый документ (если значение уникальное) или верните существующий документ (при желании)
- Зафиксируйте транзакцию. (Технически это можно объединить с предыдущим шагом.)
Вы можете создать индекс только для пустой таблицы, поэтому вам, вероятно, следует предварительно создать индекс для этого поля, а не ждать, пока у вас возникнут проблемы с производительностью, потому что QLDB выполняет полное сканирование таблицы.
Согласно ответу Мэтью Поупа, QLDB в настоящее время не поддерживает схему или уникальные индексы.
Тем не менее, реализовать это поведение в вашем приложении очень просто:
SELECT id FROM foo BY id WHERE attr = ? -- [1]
INSERT INTO foo ? -- [2]
В своем приложении вы должны утверждать, что запрос SELECT (1) не дал результатов, и запускать оператор INSERT (2) только после того, как это утверждение пройдет.
Если конкурирующая транзакция одновременно передает утверждение (1), только одна из транзакций будет зафиксирована. Другая транзакция завершится ошибкой при OCC.
Как написано выше, это уникальный атрибут, а не уникальный индекс. По соображениям производительности вы, вероятно, захотите, чтобы атрибут был проиндексирован так, чтобы запрос SELECT (1) не выполнял сканирование таблицы.
CREATE INDEX ON foo (attr)