SQL дизайн таблицы с общими и четкими данными - PullRequest
2 голосов
/ 30 марта 2020

Я новичок в SQL, и мне было интересно, как создавать таблицы, когда некоторые данные являются общими, а некоторые - разными. Это не настоящий пример, но он иллюстрирует суть. Я хочу хранить данные о различных предметах. Все предметы имеют некоторые общие данные - ID, Name, Description, CountryOfOrigin, UseByDate, et c. Однако, в зависимости от типа элемента, существуют определенные c атрибуты, которые необходимо сохранить, которые различны для этого типа. Это немного похоже на наследование объектов, есть общий тип root и различные специализации типа root.

Я мог бы создать разные таблицы, по одной для каждого типа элемента, но тогда каждая таблица будет иметь свой Name, Description, CountryOfOrigin, UseByDate и др. c. Поэтому, если бы я хотел перечислить элементы по UseByDate, мне пришлось бы искать несколько таблиц. Это не похоже на хороший подход.

Итак, я думаю, может быть, я мог бы иметь одну таблицу с именем Items с общими данными, и это каким-то образом ссылалось бы на другие таблицы, которые хранят тип элемента с его спецификацией c данные. См. Примеры ниже:

CREATE TABLE Items
(
    ItemID integer PRIMARY KEY,
    Name text, -- Brand specific name or similar
    Description text,
    CountryOfOrigin text,
    UseByDate date
);

CREATE TABLE MilkVariety
(
    Type milk_type, -- FullFat, Skimmed, etc
    VolumeLitres integer,
    FatContent integer,
    PricePerLitre money
);

CREATE TABLE BreadVariety
(
    Type bread_type, -- White, WholeGrain, Baguette, etc
    WeightKilos integer,
    SugarContent integer,
    PricePerKilo money
);

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

Есть какие-либо предложения о том, как обращаться с этими вещами? Спасибо.

Ответы [ 2 ]

0 голосов
/ 01 апреля 2020

Как я понимаю, в вашем примере весь заголовок из xVariety таблиц уникален и неприводим (KEY). Давайте примем это, а также согласимся с тем, что мы счастливы, что таблицы находятся в 1NF, и оставим все как есть.
Давайте также согласимся, что количество xVariety таблиц является управляемым, скажем, менее 30 - не рекомендуется для более.

Опция 1

Это предпочтительный вариант.

Начиная с нового Variety, супертип всех других xVariety таблиц. VAR_ID может быть (автоматическим приращением) целым числом, сгенерированным в (для) этой таблице; VAR_TYP является дискриминатором.
Создайте новый {VAR_ID, VAR_TYP} в этой таблице перед вставкой новой строки в любую из xVariety таблиц,

-- Variety VAR_ID of type VAR_TYP exists.
--
Variety {VAR_ID, VAR_TYP}
     PK {VAR_ID}
     SK {VAR_ID, VAR_TYP}

CHECK (VAR_TYP IN ('Bread', 'Milk'))

xVariety подтипы являются эксклюзивными, поэтому VAR_TYP добавлен к каждому подтипу для лучшего контроля, примечание FK {VAR_ID, VAR_TYP}.

MilkVariety {
        VAR_ID
      , VAR_TYP   DEFAULT 'Milk'

      , MilkType    -- FullFat, Skimmed, etc
      , VolumeLitres
      , FatContent
      , ...  -- Other columns specific to this variety
      }
   PK {VAR_ID}
   AK {MilkType, VolumeLitres, FatContent, ...}

           FK {VAR_ID, VAR_TYP} REFERENCES
      Variety {VAR_ID, VAR_TYP}

      CHECK (VAR_TYP = 'Milk')


BreadVariety {
        VAR_ID
      , VAR_TYP   DEFAULT 'Bread'

      , BreadType   -- White, WholeGrain, etc
      , WeightKilos
      , SugarContent
      , ...  -- Other columns specific to this variety
      }
   PK {VAR_ID}
   AK {BreadType, WeightKilos, SugarContent, ...}

           FK {VAR_ID, VAR_TYP} REFERENCES
      Variety {VAR_ID, VAR_TYP}

    CHECK (VAR_TYP = 'Bread')

Items теперь может ссылаться Variety.

Items { ItemID
      , Name_
      , Description
      , CountryOfOrigin
      , UseByDate

      , VAR_ID
      }
   PK {ItemID}

   FK {VAR_ID} REFERENCES Variety {VAR_ID}

Опция 2

Эта опция обеспечивает меньший контроль, но может быть проще в управлении.

Каждая таблица имеет свой независимый (автоинкремент) ID; снова добавив VAR_TYP для лучшего контроля.

MilkVariety {
         MILK_ID
       , VAR_TYP    DEFAULT 'Milk'

         MilkType      -- FullFat, Skimmed, etc
       , VolumeLitres
       , FatContent
       , ...  -- Other columns specific to this variety
       }
    PK {MILK_ID}
    AK {MilkType, VolumeLitres, FatContent, ...}

    CHECK (VAR_TYP = 'Milk')


BreadVariety {
         BREAD_ID
       , VAR_TYP    DEFAULT 'Bread'

         BreadType     -- White, WholeGrain, etc
       , WeightKilos
       , SugarContent
       , ...  -- Other columns specific to this variety
       }
    PK {BREAD_ID}
    AK {BreadType, WeightKilos, SugarContent, ...}

    CHECK (VAR_TYP = 'Bread')

Теперь view {VAR_TYP, VAR_TYP_ID}.

-- view (logically)
--
Variety {VAR_TYP, VAR_TYP_ID}
     PK {VAR_TYP, VAR_TYP_ID}

Пример:

CREATE VIEW Variety AS
SELECT VAR_TYP
     , MILK_ID AS VAR_TYP_ID
FROM MilkVariety
UNION
SELECT VAR_TYP
     , BREAD_ID AS VAR_TYP_ID
FROM BreadVariety ;

Обратите внимание, что представление должно UNION всех xVariety таблиц. Было бы хорошо, если бы мы могли (как-то) материализовать эту точку зрения, тогда она могла бы быть FK возможной. Но, оставив это обсуждение на какое-то другое время.

Добавление {VAR_TYP, VAR_TYP_ID} к Items

Items { ItemID
      , Name_
      , Description
      , CountryOfOrigin
      , UseByDate

      , VAR_TYP
      , VAR_TYP_ID
      }
   PK {ItemID}

     -- how to implement this?
     FK {VAR_TYP, VAR_TYP_ID} REFERENCES
Variety {VAR_TYP, VAR_TYP_ID}

FK должно быть реализовано как-то . Если представление материализовано, в зависимости от СУБД, может быть возможно указать ограничение в SQL; в противном случае приложение должно позаботиться об этом.

Если xVariety таблицы редко меняются, скажем, раз в неделю, то представление Variety {VAR_TYP, VAR_TYP_ID} может фактически стать таблицей , Тот же процесс, который загружает xVariety таблиц, может затем заполнить таблицу с помощью запроса. В этом случае было бы возможно иметь FK для него из Items.

Используйте {VAR_TYP, VAR_TYP_ID} при объединении, чтобы не присоединиться к неправильной таблице.

SELECT *
FROM Items        AS a
JOIN BreadVariety AS b ON  b.VAR_TYP_ID = a.VAR_TYP_ID
                       AND b.VAR_TYP    = a.VAR_TYP
WHERE a.CountryOfOrigin = 'US';

Примечания

All attributes (columns) NOT NULL

PK = Primary Key
AK = Alternate Key   (Unique)
SK = Proper Superkey (Unique)
FK = Foreign Key
0 голосов
/ 30 марта 2020

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

Ваша таблица предметов выглядит хорошо. Я добавил пару столбцов внизу.

Item
----
Item ID
Name
Description
Origin Country
Use By Date
Item Variety
Variety ID

Разновидность предмета - это Varchar, который описывает сорт, как в «хлебе», «молоке». Идентификатор сорта - это внешний ключ к таблице сорта.

 Variety
 -------
 Variety ID
 Type
 Measure Type
 Measure Amount
 Content Type
 Content Amount
 Price per measure

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

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