Хобрук: Ваш путь к мастерству в программировании

Составной FK с полями, допускающими значение NULL

У меня 3 таблицы:

  • NETWORK_OPERATORs;

  • NETWORK_CELLs: каждый из них принадлежит одному NETWORK_OPERATOR;

  • IRIs: каждый из них может иметь либо:

    1. a Network Operator or
    2. Сетевая ячейка

но одно из 1) и 2) является обязательным.

В случае 1) netOpId должен существовать в NETWORK_OPERATOR таблице;

В случае 2) _7 _ + _ 8_ должен существовать в CELL таблице;

Вот пример кода DDL:

CREATE TABLE "NETWORK_OPERATOR" (
  "NETOPID" INTEGER NOT NULL, 
  "NAME" VARCHAR2(20),
  CONSTRAINT "NETWORK_OPERATOR_PK" PRIMARY KEY ("NETOPID")
)

CREATE TABLE "NETWORK_CELL" (
  "CELLID" INTEGER  NOT NULL, 
  "NETOPID" INTEGER  NOT NULL, 
  "NAME" VARCHAR2(20), 
  CONSTRAINT "NETWORK_CELL_PK" PRIMARY KEY ("CELLID"),
  CONSTRAINT "CELL_NETOPS_FK" FOREIGN KEY ("NETOPID") REFERENCES "NETWORK_OPERATOR" ("NETOPID")
)

CREATE TABLE "IRI" (
  "IRIID" INTEGER NOT NULL,
  "NETOPID" INTEGER,
  "CELLID" INTEGER,
  "NAME" VARCHAR2(20),
  CONSTRAINT "IRI_PK" PRIMARY KEY ("IRIID"),
  CONSTRAINT "IRI_NETOPS_FK" FOREIGN KEY ("NETOPID") REFERENCES "NETWORK_OPERATOR" ("NETOPID")
)

Другими словами,

NETWORK_CELL сам всегда привязан к NETWORK_OPERATOR, так что ЕСЛИ a IRI имеет netOpId, он должен быть принудительно существующим netOpId, ELSE IF a IRI имеет cellId + netOpId он должен быть существующим _19 _ + _ 20_

Я вижу 2 варианта:

Вариант 1:

Сделать только IRI.NETOPID NOT NULLable и добавить составной FK

    CREATE TABLE "IRI" (
      ...
      "NETOPID" INTEGER NOT NULL,
      "CELLID" INTEGER,
      ...
      CONSTRAINT "IRI_CELL_FK" FOREIGN KEY ("CELLID", "NETOPID") REFERENCES "NETWORK_CELL" ("CELLID", "NETOPID")

)

(конечно, на "NETWORK_CELL" ("CELLID", "NETOPID") будет уникальный ключ)

Другими словами, IRI будет иметь обязательную связь FK с оператором сети и необязательную связь FK с сетевой ячейкой.

Подозрительно то, что этот необязательный FK состоит из обязательного поля и необязательного поля на стороне IRI.

Oracle RDBMS принимает это (я только что пробовал), но насколько это хорошая практика?

Вариант 2:

Тот же FK, что и в варианте 1, но оставьте IRI.NETOPID равным NULL и добавьте настраиваемое ограничение, которое применяет либо netOpId , либо _26 _ + _ 27_

Я считаю это решение более портативным, но, возможно, ошибаюсь.

Вопрос

Есть варианты получше?

Как лучше всего справиться с этой ситуацией и почему? Я тоже думаю о переносимости на другие СУБД ...

Спасибо


  • Возможный дубликат наследования в проекте базы данных 20.03.2018
  • Привет. Это часто задаваемые вопросы. Google sql / подтипы базы данных / наследование / полиморфизм. Также много / несколько FK для многих / нескольких таблиц (анти-шаблон). Вы должны найти эти googing - Всегда гуглите много четких, кратких и конкретных версий / формулировок вашего вопроса / проблемы / цели и читайте много ответов. Добавьте в поисковые запросы релевантные ключевые слова, которые вы обнаружите. Если вы не нашли ответа, опубликуйте сообщение, используя поиск по одному варианту по заголовку и ключевым словам для тегов. PS Почти всегда самый простой и понятный дизайн начинается без NULL. Вы всегда можете использовать NULL, присоединяясь к новым базовым таблицам слева. 20.03.2018
  • @philipxy Мой вопрос не имеет отношения к наследованию. Я внимательно искал в Google лучшие практики такого рода отношений, но не нашел ответа. Кстати, спасибо за ваше предложение. Я постараюсь быть более ясным в своих объяснениях. 22.03.2018
  • Приведите минимальный воспроизводимый пример. Ваш if-elseif не имеет смысла, поскольку, если у IRI нет netOpId, тогда у него нет cellId + netOpId, поэтому elseif никогда не выполняется. Кажется, что have & + скрывает какой-то язык. Например, в комментарии вы говорите, что просто имеет операцию .... Точно так же всегда привязано к неясно, это просто что-то неясное, о чем вы сразу же пытаетесь привести. (Что, я полагаю, должно быть определением? Но вы начинаете так, не то есть.) PS Как работает FK по умолчанию MATCH SIMPLE, FK с NULL удовлетворяется. Таким образом, у вас могут быть FK (netid), (cellid) и (netid, cellid). 22.03.2018
  • Подтипирование здесь является проблемой. Есть два типа вещей того типа вещей, которые может иметь IRI. Вот еще одна ссылка. Я согласен, что это может быть не единственная проблема дизайна здесь. 22.03.2018
  • Извините, английский не мой родной язык. Я согласен с вашей точкой зрения if..else if с чисто синтаксической точки зрения. Более того, я смешивал псевдокод и код. Но я рад, что вы поняли мой вопрос :-) 23.03.2018

Ответы:


1

Ваш вариант 1 в порядке. По умолчанию режим объявления FK (внешнего ключа) MATCH SIMPLE (обычно единственный реализованный) работает, значение подстроки FK с любыми NULL удовлетворяет его ограничению. Таким образом, вы можете иметь IRI FK (нетид) и (нетид, целлид) - плюс нетид НЕ NULL. (Кажется, вы забыли NOT NULL в своем первом IRI, но не во втором.)

Тогда единственными случаями для пары столбцов являются (ненулевое, нулевое) и (ненулевое, ненулевое). Нетид должен существовать; с этим нетидом должен существовать ненулевой cellid, и NULL cellid в порядке.

22.03.2018

2

По моему мнению, одним из решений может быть следующее:

CREATE TABLE IRI (
  IRIID INTEGER NOT NULL,
  NETOPID INTEGER,
  CELLID INTEGER,
  NAME VARCHAR2(20),
  CONSTRAINT IRI_PK PRIMARY KEY (IRIID),
  CONSTRAINT IRI_NETOPS_FK FOREIGN KEY (NETOPID) REFERENCES NETWORK_OPERATOR (NETOPID),
  CONSTRAINT IRI_CELLS_FK FOREIGN KEY (CELLID) REFERENCES NETWORK_CELL (CELLID),
  CONSTRAINT IRI_CELL_OR_NETOP CHECK ( NVL(NETOPID, CELLID) IS NOT NULL )
)

Если вы хотите, чтобы было установлено только значение, вы можете использовать

CHECK ( NVL(NETOPID, CELLID) IS NOT NULL AND NOT (NETOPID IS NOT NULL AND CELLID IS NOT NULL) )

or

CHECK ( NVL(NETOPID, CELLID) IS NOT NULL AND NETOPID||CELLID IN (NETOPID, CELLID) )

or

CHECK ( (NETOPID IS NULL AND CELLID IS NOT NULL) OR (NETOPID IS NOT NULL AND CELLID IS NULL) )
16.03.2018
  • Спасибо, но ключевым моментом этой темы является то, что NetworkCell сам привязан к Оператору, так что если IRI имеет только Оператор, он должен быть привязан к NETWORK_OPERATOR только на NETOPID, но если IRI имеет Ячейку, он должен быть привязан кому: NETWORK_CELL на NETOPID + CELLID. Постараюсь внести ясность в вопрос. 16.03.2018
  • Новые материалы

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..

    Как я опубликовал свое первое приложение в App Store в 13 лет
    Как все началось Все началось три года назад летом после моего четвертого класса в начальной школе. Для меня, четвертого класса, лето кажется бесконечным, пока оно не закончится, и мой отец..

    Что в лицо
    Очерк о возвращении физиогномики и о том, почему мы должны это приветствовать. История начинается со странной науки. Р. Тора Бьорнсдоттир, Николас О. Рул. Видимость социального класса по..

    Почему шаблоны проектирования и почему нет?
    Сложность — мать всех проблем в программировании. Программное обеспечение должно быть разработано с точки зрения того, кто его поддерживает, а не того, кто его пишет, потому что программное..

    Создание дизайна обуви с помощью машинного обучения
    Обувь. Что подождать? Я думал, что речь пойдет о машинном обучении! Ну это так. Если бы вы пошли на Amazon, сколько обуви вы бы нашли? Наверное, много, не так ли? Но много ли в них..

    GraalVM в 2022 году: итоги года
    2022 год был очень продуктивным для проекта и сообщества GraalVM. Вместе мы разработали множество новых функций, выпустили GraalVM для последних версий Java и новых платформ и увидели несколько..