Hej! <b>>DataId och RevisionId är primary key i tabellen data, sen har jag en one-to-many relation mellan signal och data och en one-to-many relation mellan projekt och data. Är detta en god struktur?</b> Hej, Ok, nu ska vi bena ut detta; Hej,Databasstruktur...
Jag har en fråga om best practice...
Jag har tre tabeller (förenklade i detta exempel): signal, data och project. En signal har data som beror på vilket projekt signalen används i. Data ska kunna versionshanteras. DataId och RevisionId är primary key i tabellen data, sen har jag en one-to-many relation mellan signal och data och en one-to-many relation mellan projekt och data. Är detta en god struktur?
Hur bör jag göra om jag vill att data för en signal ska vara globala för samtliga projekt? Ska jag låta det vara möjligt att ha null i fältet ProjectId? Ska jag ha ett fält IsGlobal som kan ha värdet 0 eller 1?
Jag kan alltså se flera sätt att lösa det på men finns det ett visst rekommenderat sätt?
Signal
------
SignalId
Name
Data
----
DataId
RevisionId
SignalId
ProjectId
Data
Value
Project
-------
ProjectId
Name
Tack på förhand!
// StefanSv: Databasstruktur...
Detta är lite "nja" ur min synvinkel. Sen är jag inte med på skillnaden mellan data och value. Vidare vill jag helst kalla det Revision number snarare än id (om inte revisions finns i en egen tabell).
Jag skulle antingen ha gjort:
Signals (ID, Name)
Projects (ID, Name)
Data(ID, SignalID, ProjectID)
DataRevisions(DataID, RevisionNumber, Value)
Eller:
Signals (ID, Name)
Projects (ID, Name)
DataRevisions(SignalID, ProjectID, RevisionNumber, Value)
Eller på det sättet som du föreslår, dvs
Signals (ID, Name)
Projects (ID, Name)
Data(ID, SignalID, ProjectID, RevisionNumber, Value)
<b>Men</b> då låta ID vara surrogatnyckel, och därmed PK, och ha ett separat index på signalid, projid, revnr istället.
Alltså: Inte låta DataID förekomma flera gånger med olika revisionnumbers i Data-tabellen.
Angående signal global per projekt: En del människor tycker det är fel att använda NULL för något "viktigt". Jag har hittills inte hört ett enda argument som inte är religiöst eller handlar om att NULL är svårt/dåligt implementerat. Alternativen du har för de globala är nog bara:
1. Separat tabell. Slipper NULL-värden, ganska elegant på sitt sätt, men ofta mer jobb.
2. Tillåta nullvärden som du förslår. Tycker jag är bäst, det är tydligt och enkelt. Beror på situationen om du behöver/bör sätta indikator här eller inte. (kan det aldrig ändras? hur matas informationen in? etc)Sv:Databasstruktur...
Att kalla RevisionId för RevisionNumber köper jag då jag inte har en separat tabell. För global data kör jag på null-spåret.
Hmmm, nu är jag inte med. Varför inte låta dataid (surrogatnyckel) förekomma flera gånger med olika revisionnumbers? Jag har tänkt ha dessa ihop som en composite primary key? Det är väl hela poängen?
Att tillägga är att jag har en audit tabell där alla ändringar för alla objekt lagras.
Ett exempel på data kan ju te.x. vara
dataid: 1
revisionnumber: 1
projectid: 1
signalid: 1
data: max delay (s)
value: 10
...och så ändrar en viss användare value till 20. Då borde jag väl endast stega upp revisionnumber?
mvh
// StefanSv: Databasstruktur...
1. Vad står DataID för, hur vet du vilket DataID en ny ska ha? När ska man använda ett gammalt DataID?
På ditt senaste verkar det som att jag kanske missförstod, det ser ut som att dataid är knutet till det som står i "data" (i kombination med signal/project?).
I så fall skulle jag vilja ha en separat tabell, "data types", med kolumner id, name (och ev. signal/project om det behövs), ha ID som PK. Sen kan du ha ditt upplägg, förutom att jag skulle ta bort kolumnerna "data", project, och signal, eftersom de går att få från "data types".
2. Kompositnycklar är relativt sällan använda, förutom i relationer. (alltså: man brukar inte ha det om man inte har andra tabeller för samtliga nycklarna). Det fallet de är meningsfulla är om du har "halva" nycklar som är logiska utifrån. (ex. personnummer eller fakturanummer eller något, alltså ett unikt id som kommer utifrån, som sen ska kombineras med något annat, typ orderrad).
Man kan ändå alltid skippa det och göra en ny tabell för dem (lite mer arbete vid insert/update/delete, men personligen tycker jag det är tydligare), och då blir det en "vanlig relation" igen.
3. Vidare är jag inte med på audit-tabellen, det passar inte riktigt in. Varför vill du i så fall lagra flera värden i data-tabellen om du redan har allt historik du behöver i den andra? Det hade ju räckt med det senaste i data?Sv:Databasstruktur...
hehe, ja det får vi göra... jag har inte varit helt glasklar.
1. DataId är en int identity, liksom SignalId och ProjectId
Det jag försöker mig på är en förenklad entity-attribute-value struktur som kan versionshanteras. Om jag ändrar namn på fälten så blir det tydligare. I mitt fall är fältet data (attribute) en sträng och fältet value också en sträng.
2. Ok... detta är taget. Då låter jag alltså revisionnumber vara en helt vanlig int.
3. I audit sparas data om alla "events" som sker, t.ex. när ny data skapas, när data ändras, när data tas bort, när data releasas (för varje rad i tabellen data är även ett state (new, released, obsolete) kopplat) osv osv... Dessutom är det inte bara tabellen data som spåras utan även andra tabeller. I audit tabellen lagras alltså vilken typ av entity det är som ändrats och dess id. På detta sätt tänkte jag att jag slipper ha med fälten datum, användarid, action för varje rad i data tabellen...
Detta kanske inte är det bästa sättet, men det håller nere storleken på systemet. Å andra sidan kan det ju leda till sämre prestanda...
tack för hjälpen.
// Stefan