SQL: как обеспечить, чтобы в группе столбцов был установлен только один столбец - PullRequest
10 голосов
/ 07 июня 2009

В SQL существует ли способ принудительно установить, что только один столбец из группы столбцов имеет значение, а остальные имеют значение null? Может быть, ограничение или триггер? Этот тип вещей может быть для справочной таблицы, но есть ли альтернативные схемы таблиц, которые могли бы достичь этого лучше?

Например:

ID    OtherTable1ID    OtherTable2ID    OtherTable3ID
-----------------------------------------------------
1     23               NULL             NULL
2     NULL             45               NULL
3     33               55               NULL   -- NOT ALLOWED

Основная проблема заключается в том, что все эти столбцы являются FK для других таблиц, поэтому я не могу свернуть их до одного столбца.

Я использую SQL Server, но подойдет любой ответ.

Ответы [ 5 ]

14 голосов
/ 07 июня 2009

@ предложенные ограничения tvanfosson работают нормально для трех столбцов, но для общности я предпочитаю

(cast(col1 is not null, int) +
 cast(col2 is not null, int) +
 cast(col3 is not null, int)) = 1

потому что он лучше обобщает любое количество столбцов с «линейно растущим» (а не «квадратично растущим») объемом кодирования (это даже лучше в диалектах SQL, которые не требуют явного приведения логического бита, иначе говоря, к int, Я не уверен, является ли SQL Server одним из них).

6 голосов
/ 07 июня 2009

Должно работать следующее ограничение:

 (column1 is null and column2 is null)
   or (column1 is null and column3 is null)
   or (column2 is null and column3 is null)

Однако это не заставит его содержать ненулевой столбец. Для этого добавьте еще одно ограничение:

 column1 is not null
    or column2 is not null
    or column3 is not null
1 голос
/ 07 июня 2009

Для меня это выглядит как плохое дизайнерское решение. Поскольку ID является первичным ключом в этой таблице, он будет допустимым значением для всех отношений внешнего ключа. Это означает, что вам нужно очень усердно работать на внешнем уровне / уровне бизнеса, чтобы гарантировать, что значения находятся в допустимом диапазоне.

Например, при настройке таблиц для таблицы 2 абсолютно допустимо использовать 1 в качестве значения поиска вместо 2, которое предполагается использовать - и база данных не будет его перехватывать.

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

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

1 голос
/ 07 июня 2009
CREATE TABLE Repro.Entity
(
    entityId INTEGER IDENTITY (1, 1) NOT NULL,
    column1 INTEGER,
    column2 INTEGER,
    column3 INTEGER,
    CONSTRAINT Entity_PK PRIMARY KEY(entityId),
    CONSTRAINT Entity_CK CHECK(
        (column1 IS NOT NULL AND column2 IS NULL AND column3 IS NULL) OR 
        (column1 IS NULL AND column2 IS NOT NULL AND column3 IS NULL) OR 
        (column1 IS NULL AND column2 IS NULL AND column3 IS NOT NULL))
)
0 голосов
/ 07 июня 2009

Мне кажется, что вы хотите использовать один столбец для набора этих вещей. Возможно, вы можете использовать какой-то тег, чтобы сказать, что это Foo,3 или Bar,7 или Baz,9?

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