ER2RM - Mapping - Transformation

Input til denne algoritme er et færdigt ER-diagram, som udtrykker en grundig semantisk model for en kommende database. Algoritmens output er en database udtryk ved et antal create table-sætninger. De ni trin er:

  1. Behandling af alle ordinære entiteter
  2. Behandling af alle svage entiteter
  3. Binære 1:1-relationer
  4. Binære 1:N-relationer
  5. Binære N:M-relationer
  6. Flerværdiattributter
  7. N-ære relationer
  8. Specialiseringer/Generaliseringer
  9. Aggregeringer

Svarende til alle ordinære entiteter oprettes en tilsvarende relation (tabel) i databasen. I praksis gøres dette ved, at der skrives en create table-sætning. Der skal selvfølgelig erklæres en nøgle primary key i den nye relation. Den vælges arbitrært blandt kandidatnøglerne. De ikke valgte kandidatnøgler, alternativnøglerne, pålægges reglen unique i relationen.


create table e1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      unique(an)
);

create table e2(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);


create table e1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);

create table we(
      ck <datatype> not null,
      lnr <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck, lnr),
      foreign key(ck) references e1(ck)
);

Vi er nu nået til overvejelser vedrørende ER-modellens relationer. Hvad skal der ske med dem? Heuristisk design siger i bogen Relational Database Query Languages at der altid er et heuristisk alternativ til hvad man ellers måtte overveje. Det heuristiske design består i, at der oprettes en relation, tabel, til repræsentation af ER-relationen i databasen. Da det altid kan bruges bliver det vores default.

Når det kaldes et alternativ, er det fordi, der i en række tilfælde er en mulighed for at arbejde uden denne tabel, og det, vel at mærke, uden at miste information. Vi skal se hvordan.


Har 1:1-relationen partiel deltagelse til begge sider, er heuristisk metode ikke et tilbud men et krav. Vi er tvunget til oprettelse af opslagstabellen. Vi har i skridt 1 oprettet:

create table e1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      unique(an)
);

create table e2(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);

Nu opretter vi så opslagstabellen, idet vi bemærker en (midlertidig) fejl i lærebogen, således:

create table r (
      cka <datatype> not null,
      ckb <datatype> not null,
      primary key(?),
      unique(?),
      foreign key(cka) references e1(ck),
      foreign key(ckb) references e2(ck)
);

Hvordan skal denne relations primærnøgle se ud? Hvis I er i tvivl, så lav et forekomstdiagram og ræsonner jer frem til det!

Vi har gennemført en række logiske overvejelser vedrørende 1:1- og 1:n-relationer. Der er også argumenteret for, at heuristisk design altid kan anvendes. Nu kunne man så stile sig det spørgsmål, om heuristisk design kan undværes ved n:m-relationer?

Med andre ord: Kan alternativt design løse opgaven her? Hvor mange fremmednøgler ville være nødvendige i e1, og hvor mange i e2? Nej vel? Hvis det spørgsmål ikke kan besvares entydigt, ville vi få enten for få, eller nulls. Med andre ord, det er uanvendeligt her. Så svaret er heusristisk design, altså opslagstabel med Bjørns metode.


create table e1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      unique(an)
);

create table e2(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);

create table r (
      cka <datatype> not null,
      ckb <datatype> not null,
      a1  <datatype> not null,
      a2  <datatype> not null,
      an  <datatype> not null,
      primary key(?),
      unique(?),
      foreign key(cka) references e1(ck),
      foreign key(ckb) references e2(ck)
);

Når vi her i r skal etablere en primærnøgle, hvad er så kandidatnøglen? Hvorfor? Hvad læser vi i forekomsttabellen?

Mange lærebøger beskriver denne situation. Jeg undgår den fordi vi i ER-modelleringen har påtaget os, at lave svage entiteter til at indeholde værdierne for de værdier, der er, udover en. Så vi kan derfor henvise til den teori, og, hvis vi ikke har taget det i ed, gøres det nu og problemet løses derefter som beskrevet i trin 2.

I n-ære relationer, ternære eller højere, vil der altid, og med samme begrundelser som under trin 5, blive etableret en opslagstabel med Bjørns metode. Undtaget er et eneste tilfælde, hvilket? Svaret er 1:1:1:...:1 med total deltagelse fra alle N. Er bare en enkelt kardinalitet støre end 1, er der ingen vej udenom.


create table e1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      unique(an)
);

create table e2(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);

create table en(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);

create table r (
      cka <datatype> not null,
      ckb <datatype> not null,
      ckn <datatype> not null,
      primary key(?),
      unique(?),
      foreign key(cka) references e1(ck),
      foreign key(ckb) references e2(ck)
      foreign key(ckn) references en(ck),
);


create table sup1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      unique(an)
);

create table sub1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      foreign key(ck) references sup1(ck)
);

create table sub2(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      foreign key(ck) references sup1(ck)
);

Logikken er (selvfølgelig), at da både sub1 og sub2 er sup1'er så må de have samme nøgle. Det må nødvendigvis også se som hver af dem er forbundet til sup1 med en 1:1-relation med tvungen deltagelse, hvorfor fremmednøglemetoden bruges.


create table e1(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck),
      unique(an)
);

create table e2(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);

create table r1 (
      cka <datatype> not null,
      ckb <datatype> not null,
      a1  <datatype> not null,
      a2  <datatype> not null,
      an  <datatype> not null,
      primary key(?),
      unique(?),
      foreign key(cka) references e1(ck),
      foreign key(ckb) references e2(ck)
);

create table e3(
      ck <datatype> not null,
      a1 <datatype> not null,
      a2 <datatype> not null,
      an <datatype> not null,
      primary key(ck)
);

create table r2 (
      cka <datatype> not null,
      ckb <datatype> not null,
      ckc <datatype> not null,
      primary key(?),
      unique(?),
      foreign key(cka) references r1(cka),
      foreign key(ckb) references r1(ckb),
      foreign key(ckc) references e3(ck)
);

Med andre ord: Når r1 i mellemtiden er blevet en tabel, der lader som om den kommer ud af en entitet, godt nok en aggregeret entitet, tillader vi os at forbinde r2 til den.