Finns det någon här som är bra på db-design? <b>Detta är bara ett exempel på principen, men problemet är följande: Nej, knappast någon rymdstation, men en expansion i en stor produkt för ett programvaruföretag, där det finns ganska strikta policies för db-normalisering och -relationer. 1-Strikt policy för normalisering Nej, precis vad jag menade. Det är därför jag efterlyser bra idéer kring denna typ av problem. Är inte relationen mellan Car och Custoemr den som skall gälla? Tack för förslaget! Men... Det här med bilar och hyresavtal är bara ett exempel. Applikationen som jag ska bygga ut har inget alls med bilar att göra... det är principen jag är ute efter. Gick till slut på Marcus lösning. Båda varianterna funkar, så det var bara att välja en.DB-design- och normaliseringsproblem
Jag vill göra en struktur som liknar följande:
<CODE>
CARS
----
PK CarId NOT NULL
CarName
...
CAR_PROPERTIES
----
PK CarId NOT NULL
PK PropertyId NOT NULL
PK CustomerId
PropertyName
PropertyValue
...
CUSTOMERS
----
PK CustomerId NOT NULL
CustName
...
</CODE>
Detta är bara ett exempel på principen, men problemet är följande:
- Jag vill använda tabellen CAR_PROPERTIES för att lagra defaultvärden för egenskaper hos olika CARS. Rader med defaultproperties skulle alltså få CustomerId = NULL, för att kunna ha relationen till CUSTOMERS
- MEN... Det går inte att ha en NULL-bar kolumn som en del av en primärnyckel.
Ska tabellen CAR_PROPERTIES ha ytterligare en kolumn med ett unikt ID som själv får utgöra primärnyckel, samt att man då implementerar logik för att garantera att kombinationen CarId-PropertyId-CustomerId är unik (via ett UNIQUE-constraint eller en trigger)?
Vad är Best Practice för att lösa denna typen av problem?Sv: DB-design- och normaliseringsproblem
- Jag vill använda tabellen CAR_PROPERTIES för att lagra defaultvärden för egenskaper hos olika CARS. Rader med defaultproperties skulle alltså få CustomerId = NULL, för att kunna ha relationen till CUSTOMERS
- MEN... Det går inte att ha en NULL-bar kolumn som en del av en primärnyckel.
</b>
Renast och snyggast är väl kanske att du har en helt egent tabell för defaults. Teoretiskt sett är det väl mest rätt att tänka så. Men det blir kanske lite mer jobb utan någon uppenbar vinst.
En möjlig lösning är att du ger dessa default värden CustomerId = -1
Och att du sen har en "DefaultCustomer" med detta id (som anändaren aldrig får se...)
Lite äpplen och päron kanske.. med vafan, det är väl inte en rymdstation du ska bygga? ;-)
<b>
Ska tabellen CAR_PROPERTIES ha ytterligare en kolumn med ett unikt ID som själv får utgöra primärnyckel, samt att man då implementerar logik för att garantera att kombinationen CarId-PropertyId-CustomerId är unik (via ett UNIQUE-constraint eller en trigger)?</b>
Båda sätten är ok, men mycket talar för att det är klokt att ge varje tabell ett unikt id-fält.
Säg att du vill bygga ut datamodellen ytterligare t ex införa en tabell CarProperyJpgImage. Då blir främmande nyckel i den tabellen hellre en CarPropID än (CarId-PropertyId-CustomerId).
Enklare, snyggare, bättre prestand vid JOIN osv.Sv:DB-design- och normaliseringsproblem
Därför tvivlar jag på din första lösning, även om den skulle fungera. Men en renare lösning skulle vara bättre...
Om man nu tänker sig att ha en extra id-kolumn - är det möjligt att implementera ett unique-constraint som klarar av de tre övriga kolumnerna?
/PelleSv: DB-design- och normaliseringsproblem
2-"Primärnycklar" som måste tillåta null
Dessa saker verkar inte gå hand i hand...
/mickeSv:DB-design- och normaliseringsproblem
/PelleSv: DB-design- och normaliseringsproblem
När du väljer en Car, vet du (väl) vilken customer som äger den? Då är det inte ett bekymmer, för relationen Car-CarProperties är då 1-oo och funkar som vanligt: Defaultvärden saknas i tabellen helt enkelt (eller så kan du ha DEFAULT constraints)
Som det ser ut kan en Car ägas av olika Customers samtidigt - MEN den kan då ha samma eller olika properties som sig själv! Och den kan både ha - och inte ha en property, samtidigt som den ägs(eller inte ägs) av en eller flera kunder (eller inte)... Jag förstår att du inte riktigt är med :)
Förslag:
Cars -Unika bilar.
Customers - Relaterar till Cars
CarProperties- Relaterar till Cars.
Om du vill ha en lista med Bilmodeller eller nåt, så får du ha en många till många relation. Då behöver du en Models-tabell också, som relaterar till Cars - fast åt "andra hållet"
/mickeSv:DB-design- och normaliseringsproblem
Tänk dig att en Car är en hyrbil som kan hyras av noll, en eller flera Customers. En CarProperty kan t.ex. vara milkostnaden för att hyra bilen, en annan kan vara hyravtalets startdatum osv.
Defaultvärden för dessa properties lagras i CarProperties och kan ändras av biluthyrningsfirman som använder programmet (Därför lämpar sig inte default constraints). Där ett värde lagras för en Customer så överstyr detta defaultvärdet.
Fler bra lösningsförslag tas tacksamt emot.
/PelleSv: DB-design- och normaliseringsproblem
<b>Tänk dig att en Car är en hyrbil som kan hyras av noll, en eller flera Customers. En CarProperty kan t.ex. vara milkostnaden för att hyra bilen, en annan kan vara hyravtalets startdatum osv.</b>
Detta gäller enbart fallet med hyrbilar. Om jag skulle designa ett sådant system så vill jag att det data som gäller då kontraktet av hyresavtalet upprättades skall sparas undan på något sätt och att det inte kan förändras även om data i "grundtabeller" ändras. Tänk tex den vanliga order, orderrad, Item exemplet, lägger jag en order på en hammare som kostar 15,90:- så vill inte jag att orderns värde skall föndras bara för att man uppdaterar Item med ett nytt pris.
Tänkbar lösning om ej snygg
<code>
Agreement_PROPERTIES
----
PK CarId NOT NULL
PK PropertyId NOT NULL
PK CustomerId
PropertyValue
----
Car_PROPERTIES
----
PK CarId NOT NULL
PK PropertyId NOT NULL
PropertyName
DefaultPropertyValue
----
</code>
I car_properties lägger du defaultpratmetrar för din hyrbil, när du skapar ett nytt hyresavtal gör du en insert på dem till Agreement_PROPERTIES som representerar hyresavtalet. På det sättet får du data som inte kommer att förändras när defaultdata ändras och en lösning som inte ligger alltför långt ifrån din nuvarande lösning. Då har du separareat defaultdata från data som faktiskt gäller för ett hyreskontrakt.Sv:DB-design- och normaliseringsproblem
Vad sägs då om den här lösningen:
<CODE>
CARS
----
PK CarId NOT NULL
CarName
...
CAR_PROPERTIES
----
PK PropertyId NOT NULL
PropertyName
...
CAR_AGREEMENT
----
PK CarPropertyId NOT NULL
CarId NOT NULL
PropertyId NOT NULL
CustomerId
PropertyValue
...
CUSTOMERS
----
PK CustomerId NOT NULL
CustName
...
</CODE>
Då måste man iofs skapa ett UNIQUE-constraint på CarId, PropertyId och CustomerId i CAR_AGREEMENT, men jag har nu kollat upp att det går att göra. En av de stora fördelarna med denna typ av constraints är att de går att applicera på null-bara kolumner. Jag förstår faktiskt inte alls varför detta inte går att göra med en primärnyckel.
Vilken lösning är bäst: att lagra default-värdet (som ska gå att ändra inifrån programmet) i CAR_PROPERTIES (som i Marcus exempel) eller att lagra det i CAR_AGREEMENT med CustomerId = NULL (som i mitt exempel)?
När man bara har ett fält (PropertyValue) som ska kunna existera dels som default-värde och dels per avtal, så framstår Marcus lösning som snyggare. Om det däremot finns fler värden förutom PropertyValue som kan variera per avtal, t.ex. PropertyIsVisibleInAgreement, PropertyIsChangeableInAgreement mm - då blir det inte lika självklart. Då skulle ju ett flertal kolumner finnas upprepade i två tabeller. Är det bra? Det kräver ju olika logik beroende på om det är ett defaultvärde som ändras eller ett avtalsvärde. Samma sak vid hämtning.Sv: DB-design- och normaliseringsproblem