Jak modelować typ obiektu, który może mieć różne zestawy atrybutów?

11

Mam pewne problemy w odtworzenie bazy danych z jednego do wielu (1: M) relacji między użytkownikami i przedmioty .

To jest całkiem proste, tak; jednak każdy przedmiot należy do określonej kategorii (np. samochód , łódź lub samolot ), a każda kategoria ma określoną liczbę atrybutów, np .:

Car Struktura:

+----+--------------+--------------+
| PK | Attribute #1 | Attribute #2 |
+----+--------------+--------------+

Boat Struktura:

+----+--------------+--------------+--------------+
| PK | Attribute #1 | Attribute #2 | Attribute #3 |
+----+--------------+--------------+--------------+

Plane Struktura:

+----+--------------+--------------+--------------+--------------+
| PK | Attribute #1 | Attribute #2 | Attribute #3 | Attribute #4 |
+----+--------------+--------------+--------------+--------------+

Z powodu tej różnorodności w liczbie atrybutów (kolumn) początkowo pomyślałem, że dobrym pomysłem byłoby utworzenie jednej oddzielnej tabeli dla każdej kategorii , więc uniknęłbym kilku wartości NULL, a tym samym lepiej wykorzystałem indeksowanie.

Chociaż na początku wyglądało to świetnie, nie mogłem znaleźć sposobu na stworzenie relacji między Przedmiotami a Kategoriami za pośrednictwem bazy danych, ponieważ przynajmniej z mojego skromnego doświadczenia jako administratora bazy danych, podczas tworzenia kluczy obcych, wyraźnie informuję bazę danych nazwa i kolumna tabeli.

Na koniec, chciałbym solidną konstrukcję do przechowywania wszystkich danych, mając jednocześnie wszelkie środki, aby wymienić wszystkie atrybuty wszystkich pozycjach Użytkownik może mieć z jednej kwerendy.

Mogłem zakodować dynamiczne zapytania za pomocą języka po stronie serwera , ale uważam, że jest to błędne i niezbyt optymalne.

Dodatkowe informacje

Oto moje odpowiedzi na komentarze MDCCL:

1. Ile jest interesujących kategorii przedmiotów w kontekście biznesowym, trzy (tj. Samochody , łodzie i samoloty ) lub więcej?

W rzeczywistości jest to bardzo proste: w sumie jest tylko pięć kategorii .

2. Czy ten sam przedmiot zawsze będzie należeć do tego samego użytkownika (to znaczy, że gdy dany przedmiot zostanie „przypisany” do określonego użytkownika, nie można go zmienić)?

Nie, mogą się zmienić. W fikcyjnym scenariuszu pytania byłoby to tak, jakby Użytkownik A sprzedawał Przedmiot nr 1 dla Użytkownika B , więc własność musi zostać odzwierciedlona.

3. Czy istnieją atrybuty wspólne dla niektórych lub wszystkich kategorii ?

Nieudostępnione, ale z pamięci mogę stwierdzić, że we wszystkich kategoriach występują co najmniej trzy atrybuty .

4. Czy istnieje szansa, że ​​liczność relacji między użytkownikiem a przedmiotem wynosi wiele do wielu (M: N) zamiast jeden do wielu (1: M)? Na przykład w przypadku następujących reguł biznesowych: A User owns zero-one-or-many ItemsiAn Item is owned by one-to-many Users

Nie, ponieważ Przedmioty opisują przedmiot fizyczny. Użytkownicy będą mieli ich wirtualną kopię, z których każdy będzie identyfikowany za pomocą unikalnego GUID v4

5. W odniesieniu do następującej odpowiedzi na jeden z komentarzy do pytania:

„W fikcyjnym scenariuszu pytania byłoby to tak, jakby Użytkownik A sprzedał Przedmiot nr 1 dla Użytkownika B , więc własność musi zostać odzwierciedlona.”

Wygląda na to, że planujesz śledzić ewolucję własności przedmiotu , że tak powiem. W ten sposób, jakie atrybuty chcielibyście przechowywać na temat tego zjawiska? Tylko modyfikacja atrybutu wskazująca konkretnego użytkownika, który jest właścicielem określonego elementu ?

Nie, nie bardzo. Własność może się zmienić, ale nie muszę śledzić poprzedniego właściciela .

użytkownik5613506
źródło

Odpowiedzi:

18

Zgodnie z opisem rozpatrywanego środowiska biznesowego istnieje struktura podtypu , która obejmuje Przedmiot - nadtyp - i każdą z jego kategorii , tj. Samochód , Łódź i Samolot (wraz z dwoma innymi, które nie zostały ujawnione) - podtypy—.

Poniżej opiszę metodę, którą zastosowałbym do zarządzania takim scenariuszem.

Zasady biznesowe

Aby rozpocząć wyznaczanie odpowiedniego schematu pojęciowego , niektóre z najważniejszych dotychczas ustalonych reguł biznesowych (ograniczając analizę tylko do trzech ujawnionych kategorii , aby zachować możliwie najkrótszą formę) można sformułować w następujący sposób:

  • Użytkownik posiada zero-jeden-lub-wiele przedmioty
  • Przedmiot jest własnością dokładnie-jednego użytkownika w określonym momencie
  • Pozycja może być w posiadaniu jeden do wielu użytkowników w różnych punktach czasowych
  • Przedmiot jest klasyfikowany przez dokładnie jednej kategorii
  • Przedmiot jest, w każdym czasie,
    • albo samochód
    • lub łódź
    • lub samolot

Ilustracyjny schemat IDEF1X

Rysunek 1 przedstawia schemat IDEF1X 1, który utworzyłem, aby pogrupować poprzednie formuły wraz z innymi regułami biznesowymi, które wydają się istotne:

Ryc. 1 - Struktura i kategoria podtypu typu

Nadtyp

Z jednej strony, element , nadtyp, przedstawia właściwości lub atrybuty wspólne dla wszystkich kategorii , tj.

  • CategoryCode - określony jako KLUCZ ZAGRANICZNY (FK), który odwołuje się do Category.CategoryCode i działa jako dyskryminator podtypu , tj. Wskazuje dokładną kategorię podtypu, z którym dany Element musi być połączony -,
  • OwnerId - wyróżniony jako FK, który wskazuje User.UserId , ale przypisałem mu nazwę roli 2 , aby dokładniej odzwierciedlić jej specjalne implikacje—,
  • foo ,
  • bar ,
  • Baz i
  • CreatedDateTime .

Podtypy

Z drugiej strony właściwości odnoszą się do każdej konkretnej kategorii , tj.

  • Qux i Corge ;
  • Grault , Garply and Plugh ;
  • Xyzzy , Thud , Wibble and Flob ;

są pokazane w odpowiednim polu podtypu.

Identyfikatory

Następnie Item.ItemId PRIMARY KEY (PK) migrował 3 do podtypów o różnych nazwach ról, tj.

  • CarId ,
  • BoatId i
  • PlaneId .

Stowarzyszenia wzajemnie się wykluczające

Jak pokazano, istnieje związek lub relacja liczności jeden do jednego (1: 1) pomiędzy (a) każdym wystąpieniem nadtypu i (b) jego komplementarną instancją podtypu.

Wyłącznym podtyp symbol obrazuje fakt, że podtypy wykluczają się wzajemnie, czyli konkretna pozycja występowanie może być uzupełniona tylko jednej instancji podtyp: albo jeden samochód , lub jeden samolot , albo jeden Łódź (nigdy przez dwóch lub więcej).

, Użyłem klasycznych nazw symboli zastępczych, aby upoważnić niektóre właściwości typu jednostki, ponieważ ich rzeczywiste nazwy nie zostały podane w pytaniu.

Układ logiczny na poziomie ekspozycyjnym

W związku z tym, w celu omówienia logicznego projektu ekspozytora, wyprowadziłem następujące instrukcje SQL-DDL na podstawie diagramu IDEF1X wyświetlonego i opisanego powyżej:

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- Also, you should make accurate tests to define the 
-- most convenient INDEX strategies based on the exact 
-- data manipulation tendencies of your business context.

-- As one would expect, you are free to utilize 
-- your preferred (or required) naming conventions. 

CREATE TABLE UserProfile (
    UserId          INT      NOT NULL,
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    BirthDate       DATE     NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    Username        CHAR(20) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT UserProfile_PK  PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- ALTERNATE KEY.
);

CREATE TABLE Category (
    CategoryCode     CHAR(1)  NOT NULL, -- Meant to contain meaningful, short and stable values, e.g.; 'C' for 'Car'; 'B' for 'Boat'; 'P' for 'Plane'.
    Name             CHAR(30) NOT NULL,
    --
    CONSTRAINT Category_PK PRIMARY KEY (CategoryCode),
    CONSTRAINT Category_AK UNIQUE      (Name) -- ALTERNATE KEY.
);

CREATE TABLE Item ( -- Stands for the supertype.
    ItemId           INT      NOT NULL,
    OwnerId          INT      NOT NULL,
    CategoryCode     CHAR(1)  NOT NULL, -- Denotes the subtype discriminator.
    Foo              CHAR(30) NOT NULL,
    Bar              CHAR(30) NOT NULL,
    Baz              CHAR(30) NOT NULL,  
    CreatedDateTime  DATETIME NOT NULL,
    --
    CONSTRAINT Item_PK             PRIMARY KEY (ItemId),
    CONSTRAINT Item_to_Category_FK FOREIGN KEY (CategoryCode)
        REFERENCES Category    (CategoryCode),
    CONSTRAINT Item_to_User_FK     FOREIGN KEY (OwnerId)
        REFERENCES UserProfile (UserId)  
);

CREATE TABLE Car ( -- Represents one of the subtypes.
    CarId INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Qux   CHAR(30) NOT NULL,
    Corge CHAR(30) NOT NULL,   
    --
    CONSTRAINT Car_PK         PRIMARY KEY (CarId),
    CONSTRAINT Car_to_Item_FK FOREIGN KEY (CarId)
        REFERENCES Item (ItemId)  
);

CREATE TABLE Boat ( -- Stands for one of the subtypes.
    BoatId INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Grault CHAR(30) NOT NULL,
    Garply CHAR(30) NOT NULL,   
    Plugh  CHAR(30) NOT NULL, 
    --
    CONSTRAINT Boat_PK         PRIMARY KEY (BoatId),
    CONSTRAINT Boat_to_Item_FK FOREIGN KEY (BoatId)
        REFERENCES Item (ItemId)  
);

CREATE TABLE Plane ( -- Denotes one of the subtypes.
    PlaneId INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Xyzzy   CHAR(30) NOT NULL,
    Thud    CHAR(30) NOT NULL,  
    Wibble  CHAR(30) NOT NULL,
    Flob    CHAR(30) NOT NULL,  
    --
    CONSTRAINT Plane_PK         PRIMARY KEY (PlaneId),
    CONSTRAINT Plane_to_Item_PK FOREIGN KEY (PlaneId)
        REFERENCES Item (ItemId)  
);

Jak wykazano, typ nadrzędności i każdy z typów podrzędności jest reprezentowany przez odpowiednią tabelę podstawową .

Kolumny CarId, BoatIdi PlaneId, o ograniczonej jako PK w odpowiednich tabelach, pomoc w reprezentująca koncepcyjne poziomie stowarzyszenie jeden-do-jednego w drodze ograniczenia FK § że punkt do ItemIdkolumny, która jest ograniczona jako PK w Itemtabeli. Oznacza to, że w rzeczywistej „parze” zarówno wiersze nadtypu, jak i podtypu są identyfikowane przez tę samą wartość PK; dlatego warto o tym wspomnieć

  • (a) dołączenie dodatkowej kolumny do przechowywania kontrolowanych przez system wartości zastępczych do (b) tabele oznaczające podtypy są (c) całkowicie zbędne .

§ Aby zapobiec problemom i błędom dotyczącym (szczególnie ZAGRANICZNYCH) KLUCZOWYCH definicji ograniczeń - sytuacji, o których wspominałeś w komentarzach - bardzo ważne jest, aby wziąć pod uwagę zależność istnienia występującą między różnymi dostępnymi tabelami, jak to pokazano w kolejność deklaracji tabel w strukturze DDL ekspozycyjnej, którą również dostarczyłem w tym SQL Fiddle .

Np. Dołączenie dodatkowej kolumny z właściwością AUTO_INCREMENT do tabeli bazy danych zbudowanej na MySQL.

Uwagi dotyczące integralności i spójności

Bardzo ważne jest, aby zwrócić uwagę, że w środowisku biznesowym musisz (1) upewnić się, że każdy wiersz „nadtypu” jest zawsze uzupełniany przez odpowiadający mu odpowiednik „podtypu”, a z kolei (2) gwarantuje, że Wiersz „podtyp” jest zgodny z wartością zawartą w kolumnie „dyskryminator” wiersza „nadtyp”.

Egzekwowanie takich okoliczności w sposób deklaratywny byłoby bardzo eleganckie , ale, o ile mi wiadomo, żadna z głównych platform SQL nie zapewniła odpowiednich mechanizmów. Dlatego uciekając się do kodu proceduralnego w ramach ACID TRANSACTIONS, jest to całkiem wygodne, aby te warunki były zawsze spełnione w bazie danych. Inną opcją byłoby zatrudnienie wyzwalaczy, ale mają tendencję do robienia rzeczy nieporządnych, że tak powiem.

Deklarowanie przydatnych widoków

Mając logiczny projekt taki jak ten wyjaśniony powyżej, bardzo praktyczne byłoby utworzenie jednego lub więcej widoków, tj. Tabel pochodnych, które zawierają kolumny, które należą do dwóch lub więcej odpowiednich tabel podstawowych . W ten sposób możesz np. WYBRAĆ bezpośrednio z tych widoków bez konieczności zapisywania wszystkich JOINÓW za każdym razem, gdy musisz pobrać „połączone” informacje.

Przykładowe dane

W związku z tym powiedzmy, że tabele podstawowe są „zapełniane” przykładowymi danymi pokazanymi poniżej:

--

INSERT INTO UserProfile 
    (UserId, FirstName, LastName, BirthDate, GenderCode, Username, CreatedDateTime)
VALUES
    (1, 'Edgar', 'Codd', '1923-08-19', 'M', 'ted.codd', CURDATE()),
    (2, 'Michelangelo', 'Buonarroti', '1475-03-06', 'M', 'michelangelo', CURDATE()),
    (3, 'Diego', 'Velázquez', '1599-06-06', 'M', 'd.velazquez', CURDATE());

INSERT INTO Category 
    (CategoryCode, Name)
VALUES
    ('C', 'Car'), ('B', 'Boat'), ('P', 'Plane');

-- 1. ‘Full’ Car INSERTion

-- 1.1 
INSERT INTO Item
    (ItemId, OwnerId, CategoryCode, Foo, Bar, Baz, CreatedDateTime)
VALUES
    (1, 1, 'C', 'This datum', 'That datum', 'Other datum', CURDATE());

 -- 1.2
INSERT INTO Car
    (CarId, Qux, Corge)
VALUES
    (1, 'Fantastic Car', 'Powerful engine pre-update!');

-- 2. ‘Full’ Boat INSERTion

-- 2.1
INSERT INTO Item
  (ItemId, OwnerId, CategoryCode, Foo, Bar, Baz, CreatedDateTime)
VALUES
  (2, 2, 'B', 'This datum', 'That datum', 'Other datum', CURDATE());

-- 2.2
INSERT INTO Boat
    (BoatId, Grault, Garply, Plugh)
VALUES
    (2, 'Excellent boat', 'Use it to sail', 'Everyday!');

-- 3 ‘Full’ Plane INSERTion

-- 3.1
INSERT INTO Item
  (ItemId, OwnerId, CategoryCode, Foo, Bar, Baz, CreatedDateTime)
VALUES
  (3, 3, 'P', 'This datum', 'That datum', 'Other datum', CURDATE());

-- 3.2
INSERT INTO Plane
    (PlaneId, Xyzzy, Thud, Wibble, Flob)
VALUES
    (3, 'Extraordinary plane', 'Traverses the sky', 'Free', 'Like a bird!');

--

Następnie, korzystne pogląd jest taki, który gromadzi kolumny z Item, Cari UserProfile:

--

CREATE VIEW CarAndOwner AS
    SELECT C.CarId,
           I.Foo,
           I.Bar,
           I.Baz,
           C.Qux,
           C.Corge,           
           U.FirstName AS OwnerFirstName,
           U.LastName  AS OwnerLastName
        FROM Item I
        JOIN Car C
          ON C.CarId = I.ItemId
        JOIN UserProfile U
          ON U.UserId = I.OwnerId;

--

Oczywiście można zastosować podobne podejście, aby również WYBRAĆ „pełny” Boati Planeinformacje bezpośrednio z jednej tabeli (w tych przypadkach pochodnej).

Po tym -Jeśli nie masz nic o obecności znaków NULL w wynik zestawy- z następującą definicję widoku, można, na przykład, „zbierać” kolumny z tabel Item, Car, Boat, Planei UserProfile:

--

CREATE VIEW FullItemAndOwner AS
    SELECT I.ItemId,
           I.Foo, -- Common to all Categories.
           I.Bar, -- Common to all Categories.
           I.Baz, -- Common to all Categories.
          IC.Name      AS Category,
           C.Qux,    -- Applies to Cars only.
           C.Corge,  -- Applies to Cars only.
           --
           B.Grault, -- Applies to Boats only.
           B.Garply, -- Applies to Boats only.
           B.Plugh,  -- Applies to Boats only.
           --
           P.Xyzzy,  -- Applies to Planes only.
           P.Thud,   -- Applies to Planes only.
           P.Wibble, -- Applies to Planes only.
           P.Flob,   -- Applies to Planes only.
           U.FirstName AS OwnerFirstName,
           U.LastName  AS OwnerLastName
        FROM Item I
        JOIN Category IC
          ON I.CategoryCode = IC.CategoryCode
   LEFT JOIN Car C
          ON C.CarId = I.ItemId
   LEFT JOIN Boat B
          ON B.BoatId = I.ItemId
   LEFT JOIN Plane P
          ON P.PlaneId = I.ItemId               
        JOIN UserProfile U
          ON U.UserId = I.OwnerId;

--

Kod pokazanych tutaj widoków ma jedynie charakter poglądowy. Oczywiście wykonanie niektórych ćwiczeń testowych i modyfikacji może przyspieszyć (fizyczne) wykonanie dostępnych zapytań. Ponadto może być konieczne usunięcie lub dodanie kolumn do wspomnianych widoków, zgodnie z potrzebami firmy.

Przykładowe dane i wszystkie definicje widoków są włączone do tego SQL Fiddle , aby można je było obserwować „w akcji”.

Manipulowanie danymi: Kod aplikacji lub aliasy kolumn

Wykorzystanie kodu aplikacji (jeśli to rozumiesz przez „kod specyficzny dla serwera”) i aliasy kolumn to inne istotne kwestie, o których wspomniałeś w następnych komentarzach:

  • Udało mi się obejść [JOIN] problem z kodem specyficznym dla serwera, ale tak naprawdę nie chcę tego robić - i- dodawanie aliasów do wszystkich kolumn może być „stresujące”.

  • Bardzo dobrze wyjaśnione, dziękuję bardzo. Jednak, jak podejrzewałem, będę musiał manipulować zestawem wyników podczas wyświetlania wszystkich danych ze względu na podobieństwa z niektórymi kolumnami, ponieważ nie chcę używać kilku aliasów, aby zachować czystość instrukcji.

Wskazane jest wskazanie, że podczas korzystania z kodu aplikacji jest bardzo odpowiednim zasobem do obsługi prezentacji (lub graficznych) funkcji zestawów wyników, unikanie pobierania danych w poszczególnych wierszach ma ogromne znaczenie, aby zapobiec problemom z szybkością wykonywania. Celem powinno być „pobranie” odpowiednich zestawów danych w całości za pomocą solidnych instrumentów do manipulacji danymi dostarczanych przez (precyzyjnie) zestaw silnika platformy SQL, abyś mógł zoptymalizować zachowanie swojego systemu.

Co więcej, użycie aliasów do zmiany nazwy jednej lub więcej kolumn w pewnym zakresie może wydawać się stresujące, ale osobiście uważam taki zasób za bardzo potężne narzędzie, które pomaga (i) kontekstualizować oraz (ii) ujednoznacznić znaczenie i intencję przypisaną do danego kolumny; stąd jest to aspekt, który należy dokładnie rozważyć w odniesieniu do manipulacji danymi będącymi przedmiotem zainteresowania.

Podobne scenariusze

Równie dobrze możesz znaleźć pomoc dla tej serii postów i tej grupy postów, które zawierają moje spojrzenie na dwa inne przypadki, które zawierają skojarzenia typu podtyp z wzajemnie wykluczającymi się podtypami.

Zaproponowałem również rozwiązanie dla środowiska biznesowego obejmującego klaster nadtyp-podtyp, w którym podtypy nie wykluczają się wzajemnie w tej (nowszej) odpowiedzi .


Przypisy końcowe

1 Integration Definition for Information Modeling ( IDEF1X ) to wysoce godna polecenia technika modelowania danych, która została ustanowiona jako standard w grudniu 1993 r. Przez amerykański Narodowy Instytut Standardów i Technologii (NIST). Jest solidnie oparte na (a) niektóre z autorem prac teoretycznych przez jedynego twórcy tego modelu relacyjnego , czyli dr EF Codd ; na (b) pogląd na związek z bytem , opracowany przez dr PP Chen ; a także w (c) Logical Database Design Technique, stworzonej przez Roberta G. Browna.

2 W IDEF1X nazwa roli jest wyróżniającą etykietą przypisaną do właściwości FK (lub atrybutu) w celu wyrażenia znaczenia, które posiada w zakresie odpowiedniego typu jednostki.

3 Standard IDEF1X definiuje migrację klucza jako „Proces modelowania polegający na umieszczeniu klucza podstawowego elementu nadrzędnego lub podmiotu ogólnego welemenciepodrzędnym lub encji jako klucza obcego”.

MDCCL
źródło
1
Nie jestem pewien, czy rozumiem twoje zapytanie, ale jak pokazano w układzie DDL, Itemtabela zawiera CategoryCodekolumnę. Jak wspomniano w części zatytułowanej „Względy uczciwości i spójności”:
MDCCL
1
Bardzo ważne jest, aby zwrócić uwagę, że w środowisku biznesowym musisz (1) upewnić się, że każdy wiersz „nadtypu” jest zawsze uzupełniany przez odpowiedni odpowiednik „podtypu”, a z kolei (2) gwarantuje, że Wiersz „podtyp” jest zgodny z wartością zawartą w kolumnie „dyskryminator” wiersza „nadtyp”.
MDCCL
1
Egzekwowanie takich okoliczności w sposób deklaratywny byłoby bardzo eleganckie, ale, o ile mi wiadomo, żadna z głównych platform SQL nie zapewniła odpowiednich mechanizmów. Dlatego uciekając się do kodu proceduralnego w ramach ACID TRANSACTIONS, jest to całkiem wygodne, aby te warunki były zawsze spełnione w bazie danych. Inną opcją byłoby zatrudnienie wyzwalaczy, ale mają tendencję do robienia rzeczy nieporządnych, że tak powiem.
MDCCL
1
Sedno sprawy polega na tym, że żadna implementacja SQL (w tym dialekt MySQL) nie zapewnia odpowiedniego wsparcia dla ASSERTIONS, potężnych i eleganckich narzędzi deklaratywnych, które pomogłyby uniknąć uciekania się do podejść proceduralnych (TRANSACTIONS lub TRIGGERS) lub pracować w zbędny sposób, np. , np. niepotrzebne powtarzanie CategoryColumnw tabelach oznaczających podtypy (ze wszystkimi implikacjami na poziomie logicznym [np. anomalie modyfikacji] i fizycznym poziomie abstrakcji [np. dodatkowe indeksy, większe struktury itp.]).
MDCCL
2
Dopóki żaden z dostawców / programistów systemów zarządzania bazami danych nie dostarczy WNIOSKÓW - właściwego narzędzia do tego zadania - wolę (a) podejście proceduralne - czy to TRANSAKCJE, czy TRIGGERY - niż (b) zbędny tok działania, chociaż (b) jest możliwość - której osobiście nie polecam -. Oczywiście DBA musi starannie zarządzać uprawnieniami dotyczącymi ważnych operacji na danych, które mogą być wykonywane w istotnej bazie danych, co zdecydowanie pomaga w utrzymaniu integralności danych.
MDCCL,
0

Nazwijmy główny stół Produkty. To hostuje udostępnione atrybuty. Powiedzmy, że mamy stolik samochodowy, samolotowy i łódkowaty. Te trzy tabele miałyby klucz ProductID z ograniczeniem FK w wierszu ID tabeli Product. Jeśli chcesz je wszystkie - dołącz do nich. Jeśli chcesz tylko samochody, lewy dołącz do Samochody z Produktami (lub prawy łącz produkty i samochody, ale ja wolę zawsze używać lewych stron).

Nazywa się to hierarchicznym modelem danych. W przypadku małej liczby podtabel może mieć sens w długim stole (miliony produktów).

neManiac
źródło
A potem dołączam do użytkowników z produktami?
user5613506
1
Zazwyczaj nie potrzebujesz informacji o użytkowniku, gdy zwracasz listę produktów do interfejsu użytkownika, potrzebujesz informacji o produkcie. Nie ma sensu dołączać do użytkowników i produktów i zwracać identyczne informacje o użytkowniku dla każdego zwróconego wiersza produktu. Najpierw filtrujesz według typu produktu, łącząc tabelę produktów i odpowiednią tabelę podrzędną (Samochód, Łódź ...), a następnie filtrujesz według użytkownika za pomocą klauzuli WHERE. Zasadniczo chciałbyś mieć identyfikator właściciela w tabeli produktów (FK w kolumnie identyfikatora tabeli użytkowników). Więc dodałbyś WHERE Owner = [Request.User].
neManiac,