В дополнение к ограничению CHECK и типу данных ENUM, которые упоминаются в других источниках, вы также можете написать триггер, чтобы применить желаемое ограничение.
Я не обязательно рекомендую триггер в качестве хорошего решения, я просто указываю на другой вариант, который соответствует вашим критериям не ссылаться на справочную таблицу.
Моя привычка - определять таблицы поиска вместо использования ограничений или триггеров, когда правило состоит в том, чтобы просто ограничить столбец конечным набором значений. Влияние на производительность проверки по справочной таблице ничуть не хуже, чем использование ограничений или триггеров CHECK, и намного проще управлять, когда набор значений может время от времени меняться.
Также обычной задачей является запрос набора разрешенных значений, например, для заполнения поля формы в пользовательском интерфейсе. Когда разрешенные значения находятся в таблице поиска, это намного проще, чем когда они определены в списке литеральных значений в ограничении CHECK или определении ENUM.
Комментарий: «Как сделать поиск без идентификатора»
CREATE TABLE LookupStrings (
string VARCHAR(20) PRIMARY KEY
);
CREATE TABLE MainTable (
main_id INT PRIMARY KEY,
string VARCHAR(20) NOT NULL,
FOREIGN KEY (string) REFERENCES LookupStrings (string)
);
Теперь вы можете быть уверены, что никакое значение в MainTable.string
недопустимо, так как ссылочная целостность предотвращает это. Но вам не нужно присоединяться к таблице LookupStrings
, чтобы получить строку, когда вы запрашиваете MainTable
:
SELECT main_id, string FROM MainTable;
См? Не присоединяйтесь! Но вы получите строковое значение.
Комментарий к нескольким столбцам внешнего ключа:
Вы можете иметь два отдельных внешних ключа, каждый из которых может указывать на разные строки в таблице поиска. Столбец внешнего ключа не обязательно должен называться так же, как столбец в ссылочной таблице.
Мой типичный пример - база данных отслеживания ошибок, в которой один пользователь сообщил об ошибке, но назначил ее для исправления другим пользователем. И reported_by
, и assigned_to
являются внешними ключами, ссылающимися на таблицу Accounts
.
CREATE TABLE Bugs (
bug_id INT PRIMARY KEY,
reported_by INT NOT NULL,
assigned_to INT,
FOREIGN KEY (reported_by) REFERENCES Accounts (account_id),
FOREIGN KEY (assigned_to) REFERENCES Accounts (account_id)
);