У меня есть таблица SQLite с двумя ограничениями:
CREATE TABLE t (a INTEGER, b INTEGER, c INTEGER,
UNIQUE (b, c), PRIMARY KEY (a, c));
Я хотел бы сделать INSERT
, который игнорирует записи, которые нарушают ограничение (a, c)
, даже если ограничение (b, c)
также нарушается, но завершается неудачей, если only ограничение (b, c)
нарушается.
Другими словами, если я начну с этого:
INSERT INTO t (a, b, c) VALUES (1, 2, 3);
Это ничего не должно делать молча:
INSERT INTO t (a, b, c) VALUES (1, 2, 3);
но это должно быть ошибкой:
INSERT INTO t (a, b, c) VALUES (4, 2, 3);
Если я попытаюсь сделать это с относительно новым PostgreSQL-подобным синтаксисом UPSERT:
INSERT INTO t (a, b, c) VALUES (1, 2, 3) ON CONFLICT (a, c) DO NOTHING;
он делает то, что мне нужно с SQLite 3.26 , но он терпит неудачу из-за нарушения ограничения (b, c
) на SQLite 3.24, и changelog создает впечатление, что это может быть несчастный случай, а не признак того, что желаемое поведение гарантировано.
Если вместо определения ограничения я задаю разрешение конфликта,
CREATE TABLE t (a INTEGER, b INTEGER, c INTEGER,
UNIQUE (b, c), PRIMARY KEY (a, c) ON CONFLICT IGNORE);
затем я получаю желаемое поведение с обеими версиями (хорошо), но мне остается только подумать, полагаюсь ли я на неопределенное поведение (плохо).
Другими словами, есть ли какая-либо гарантия того, что будет, если будет нарушено несколько ограничений, но с разной (явной или неявной) обработкой конфликтов?
FWIW, порядок разрешения конфликтов не связан с порядком, в котором определены ограничения - в любом из указанных выше случаев изменение порядка определения ограничений не меняет поведение.