Уникальное ограничение SQL, если столбцу присвоено значение x - PullRequest
5 голосов
/ 19 января 2011

есть ли способ в SQL создать ограничение, что столбец должен быть уникальным, если конкретный столбец имеет определенное значение?

Пример: строки на самом деле не удаляются, но помечаются как удаленные'в базе данных.И в «не удаленных» строках ValueA должно быть уникальным:

ID    ValueA          ValueB            Deleted
-----------------------------------------------------
1     'foo'           10               0
2     'bar'           20               0
3     'bar'           30               1
4     'bar'           40               1
5     'foo'           50               0 --NOT ALLOWED

Я думал о чем-то вроде ограничения CHECK, однако я не знаю, как это сделать.

Ответы [ 5 ]

4 голосов
/ 19 января 2011

с SQL92 это невозможно, может быть, вы могли бы реализовать что-то с помощью триггера

1 голос
/ 19 января 2011

Можете ли вы немного изменить дизайн?

Мне кажется, у вас есть список "штучек".Для каждого ValueA есть единственная активная штука в любой момент времени.Лучше всего это смоделировать следующим образом:

  1. Удалить ValueA и удалено из вашей основной таблицы Thingies.

  2. Создать новую таблицу ActiveThingies со столбцами ValueAи ID.Защитите эту таблицу, сделав ValueA уникальным или первичным ключом.(Вам также может понадобиться сделать идентификатор уникальным, в зависимости от того, может ли один идентификатор представлять более 1 значения A.)

Теперь используйте таблицу ActiveThingies, чтобы контролировать, какая запись является текущей вв любой момент.Чтобы изменить активную (не удаленную) запись для «foo», обновите ее столбец ID в ActiveThingies.

Чтобы получить список не удаленных элементов, объедините две таблицы.

С этимдизайн, однако, вы потеряете способность помнить ValueA для "удаленных" "штуковин".Если вам нужно запомнить эти значения, вам также необходимо включить столбец ValueA в Thingies.

0 голосов
/ 03 февраля 2015

Для решения этой проблемы есть обходной путь - создайте еще один столбец Удален_в

deleted_on timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'

и создайте уникальный ключ как для ValueA , так и для selected_on

UNIQUE KEY not_deleted (ValueA, deleted_on)

При мягком удалении записи вставьте NOW() для значения deleted_on

0 голосов
/ 20 января 2011

Разделите вашу таблицу на две таблицы: одну, которая имеет ограничение UNIQUE для ValueA, и другую, которая не имеет. Используйте триггеры view + для объединения двух таблиц. Что-то вроде:

CREATE TABLE _Active (
    ID       INTEGER,
    ValueA   VARCHAR(255) UNIQUE,
    ValueB   INTEGER
);

CREATE TABLE _Deleted (
    ID       INTEGER,
    ValueA   VARCHAR(255), /* NOT unique! */
    ValueB   INTEGER
);

CREATE VIEW Thingies AS
    SELECT ID, ValueA, ValueB, 0 AS Deleted FROM _Active
UNION ALL
    SELECT ID, ValueA, ValueB, 1 AS Deleted FROM _Deleted;

CREATE TRIGGER _trg_ii_Thingies_Active
    INSTEAD OF INSERT ON Thingies
    FOR EACH ROW WHEN NOT NEW.Deleted
BEGIN
    INSERT INTO _Active(ID, ValueA, ValueB)
        VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;

CREATE TRIGGER _trg_ii_Thingies_Deleted
    INSTEAD OF INSERT ON Thingies
    FOR EACH ROW WHEN NEW.Deleted
BEGIN
    INSERT INTO _Deleted(ID, ValueA, ValueB)
        VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;

/* Add triggers for DELETE and UPDATE as appropriate */

(Я не уверен в синтаксисе CREATE TRIGGER, но вы понимаете, о чем я.)

0 голосов
/ 19 января 2011

MySQL игнорирует ограничения CHECK, поэтому вы не можете сделать это в MySQL, как в другой базе данных.

Вот хак. Уникальное ограничение на значение A + удалено. При удалении строк нельзя использовать только 1, они должны быть 1, 2, 3 ...

Это, по крайней мере, позволяет вам делать это на стороне сервера в MySQL, но вводит шаг. При пометке строки для удаления вы должны сначала найти максимальное (удаленное), добавить 1 и вставить это значение при пометке для удаления.

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