2 Stimmen

Wie kann man diese Mehrfachvererbungsbeziehung mit einem RDBMS modellieren?

Ich sehe mir dieses Datenmodell an, das ich mir ausgedacht habe, und fühle mich nicht wohl dabei. Ich habe die Entitätsnamen geändert, damit es (hoffentlich) mehr Sinn macht. Auf jeden Fall, wie würden Sie das folgende Modell?

Ich habe 3 Entitäten. GovernmentCustomer, PrivateCustomer, PublicCustomer. Private und PublicCustomer sind beide CorporateCustomers. Firmenkunden und Behördenkunden sind Konten. Alle Konten teilen sich denselben Schlüsselraum (wenn also PrivateCustomer eine PK von 1 hat, sollte es nicht möglich sein, dass Public oder GovernmentCustomer eine PK von 1 haben). CorporateCustomers haben einige 1:M-Beziehungen, die GovernmentCustomers nicht haben. PublicCustomers haben einige 1:M-Beziehungen, die PrivateCustomers nicht haben.

Das Erbe:

Account
  CorporateCustomer
    PrivateCustomer
    PublicCustomer
  GovernmentCustomer

Zurzeit hat mein Modell 5 Tabellen. Die Tabelle "Konto" ist die Wurzel dieser Hierarchie, wobei die PK jeder untergeordneten Tabelle eine FK zur PK der übergeordneten Tabelle ist. Alle Tabellen haben also die gleiche PK.

Also ja, wie würden Sie das modellieren? Ich hoffe, dass hier nicht irgendetwas völlig schief gelaufen ist :).

EDIT:

Außerdem: - Ich möchte, dass sich die DB um die Integrität der Schiedsrichter kümmert, nicht die App. - Es ist nicht möglich, dass ein CorporateCustomer existiert, ohne entweder ein privater oder öffentlicher Kunde zu sein. Es ist abstrakt.

0voto

Brad Punkte 2201

Ich weiß, dass diese Frage sehr alt ist, aber da es noch keine akzeptierte Antwort darauf gibt, habe ich ein paar Ideen.

Eine Möglichkeit ist die Verwendung von ORDBMS-Funktionen - mit anderen Worten, die Tabellenvererbung. In PostgreSQL könnten Sie dies so modellieren:

(Siehe die Dokumentation über die PostgresSQL-Vererbung http://www.postgresql.org/docs/9.3/static/ddl-inherit.html )

CREATE TABLE account
(
   account_id INT,
   PRIMARY KEY(account_id)
);

CREATE TABLE corporate_customer
(
   company_name VARCHAR(32),
   country_code CHAR(2),
   PRIMARY KEY(company_name)
) INHERITS(account);

CREATE TABLE private_corp_customer
(
   private_comp_id INT,
   company_owner VARCHAR(32),
   PRIMARY KEY(private_comp_int)
) INHERITS(corporate_customer);

CREATE TABLE public_corp_customer
(
   stock_ticker VARCHAR(6),
   PRIMARY KEY(stock_ticker)
) INHERITS(corporate_customer);

CREATE TABLE government_customer
(
   dept_nbr INT,
   country CHAR(2),
   PRIMARY KEY(dept_nbr)
) INHERITS(account);

Verschiedene DBMS-Anbieter werden dies auf unterschiedliche Weise umsetzen. Bei PostgresSQL gibt es einige wichtige Vorbehalte, die hier beschrieben werden:

http://ledgersmbdev.blogspot.com/2012/08/postgresql-or-modelling-part-3-table.html

Beachten Sie insbesondere den Teil, dass Primär- und Fremdschlüssel nicht vererbt werden.

Wenn Ihnen die Beschränkungen Ihres DBMS nicht gefallen oder Sie ein DBMS verwenden, das keine objektrelationalen Funktionen hat, besteht eine weitere Möglichkeit darin, eine im obigen Artikel vorgeschlagene Alternative zu verwenden und Sekundärschlüssel zu benutzen. Das würde wie folgt aussehen:

CREATE TABLE account
(
   account_id INT,
   account_type INT NOT NULL,
   PRIMARY KEY(account_id),
   UNIQUE (account_id, account_type)
);

CREATE TABLE corporate_customer
(
   account_id INT,
   account_type INT NOT NULL CHECK(account_type IN (1,2)),
   company_name VARCHAR(32),
   country_code CHAR(2),
   PRIMARY KEY(account_id, account_type),
   FOREIGN KEY(account_id, account_type) REFERENCES account(account_id, account_type),
   UNIQUE(account_id, account_type, company_name)
);

CREATE TABLE private_corp_customer
(
   account_id INT,
   account_type INT NOT NULL CHECK(account_type = 1),
   company_name VARCHAR(32),
   company_owner VARCHAR(32),
   PRIMARY KEY(account_id, account_type, company_name),
   FOREIGN KEY(account_id, account_type, company_name) REFERENCES corporate_customer (account_id, account_type, company_name)
);

CREATE TABLE public_corp_customer
(
   account_id INT,
   account_type INT NOT NULL CHECK (account_type = 2),
   company_name VARCHAR(32),
   stock_ticker CHAR(6),
   PRIMARY KEY(account_id, account_type, company_name),
   FOREIGN KEY(account_id, account_type, company_name) 
   REFERENCES corporate_customer (account_id, account_type, company_name)
) INHERITS(corporate_customer);

CREATE TABLE government_customer
(
   account_id INT,
   account_type INT NOT NULL CHECK(account_type = 3),
   dept_nbr INT,
   country_code CHAR(2),
   PRIMARY KEY(account_id, account_type),
   FOREIGN KEY(account_id, account_type) REFERENCES account(account_id, account_type),
   UNIQUE(account_id, account_type, dept_nbr)
 );

Der oben beschriebene Entwurf hat auch einige wichtige Einschränkungen (die ebenfalls in dem oben genannten Artikel beschrieben werden). Zum einen sollte es nicht möglich sein, ein Konto zu haben, das weder ein privater noch ein öffentlicher noch ein staatlicher Kunde ist, aber es ist möglich; man kann einfache Konten haben, Firmenkonten, die weder öffentlich noch privat sind... das wird ein Alptraum in der Verwaltung. Die CHECK Auch Einschränkungen können die Leistung beeinträchtigen, und Sie werden feststellen, dass sowohl Daten in den untergeordneten Entitäten dupliziert werden als auch Informationen in den untergeordneten Entitäten des Unternehmens fehlen (country_code).

Für welche Einschränkungen Sie sich entscheiden, hängt von Ihrem DBMS-Anbieter ab und davon, wie viel Kopfzerbrechen Sie sich machen wollen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X