Progettazione di database
-
05-07-2019 - |
Domanda
Sto realizzando una webapp in questo momento e sto cercando di orientarmi nella progettazione del database.
Ho un modello utente (nome utente (che è la chiave primaria), password, email, sito Web) Ho un modello di iscrizione (id, titolo, contenuto, commenti, commentCount)
Un utente può commentare una voce una sola volta. Qual è il modo migliore e più efficiente per farlo?
Al momento, sto pensando a un'altra tabella con nome utente (dal modello utente) e ID voce (dal modello voce)
**username id**
Sonic 4
Sonic 5
Knuckles 2
Sonic 6
Amy 15
Sonic 20
Knuckles 5
Amy 4
Quindi, per elencare i commenti per la voce 4, cerca id = 4.
Nota a margine: Invece di archiviare un commento, sarebbe meglio calcolare il conteggio dei commenti dal database ogni volta che è necessario?
Soluzione
Il tuo design è sostanzialmente solido. La tua terza tabella dovrebbe essere denominata come UsersEntriesComments, con i campi UserName, EntryID e Comment. In questa tabella, avresti una chiave primaria composta composta dai campi UserName e EntryID; questo imporrebbe la regola che ogni utente può commentare ogni voce una sola volta. La tabella avrebbe anche vincoli di chiave esterna tali che UserName deve essere nella tabella Users e EntryID deve essere nella tabella Entries (il campo ID, in particolare).
Puoi aggiungere un campo ID alla tabella Users, ma molti programmatori (incluso me stesso) sostengono l'uso di " natural " chiavi ove possibile. Poiché i nomi utente devono essere univoci nel sistema, questa è una chiave primaria perfettamente valida (e facilmente leggibile).
Aggiorna : rileggi la tua domanda. Non sono necessari i campi Commenti o Commenti nella tabella Voci. I commenti verrebbero correttamente memorizzati nella tabella UsersEntriesComments e i conteggi verrebbero calcolati dinamicamente nelle tue query (risparmiando il problema di aggiornare questo valore tu stesso).
Aggiornamento 2 : James Black fa un buon punto a favore di non utilizzando UserName come chiave primaria e aggiungendo invece una chiave primaria artificiale alla tabella (UserID o alcuni di questi). Se si utilizza UserName come chiave primaria, consentire a un utente di modificare il proprio nome utente è più difficile, poiché è necessario modificare anche il nome utente in tutte le tabelle correlate.
Altri suggerimenti
Cosa intendi esattamente con
entry model(id, title, content, **comments**, commentCount)
(enfasi sulla mia)? Dal momento che sembra che tu abbia più commenti per entità, dovrebbero essere archiviati in una tabella separata:
comments(id, entry_id, content, user_id)
entry_id
e user_id
sono chiavi esterne delle rispettive tabelle. Ora devi solo creare un indice univoco su ( entry_id
, user_id
) per assicurarti che l'utente possa aggiungere un solo commento per entità.
Inoltre, potresti voler creare una chiave primaria surrogata (numerica, generata tramite sequenza / identità) per la tabella degli utenti invece di impostare il nome utente come PK.
Ecco la mia raccomandazione per il tuo modello di dati:
UTENTI tabella
- USER_ID (pk, int)
- USER_NAME
- PASSWORD
- sito web
ENTRY tabella
- ENTRY_ID (pk, int)
- ENTRY_TITLE
- CONTENUTO
ENTRY_COMMENTS tabella
- ENTRY_ID (pk, fk)
- USER_ID (pk, fk)
- COMMENTO
Questa configurazione consente a un ENTRY di avere più di 0 commenti. Quando viene aggiunto un commento, la chiave primaria è una chiave composita di ENTRY_ID
e USER_ID
significa che la coppia può esistere solo una volta nella tabella (IE: 1, 1 vinto ' consenti di aggiungere nuovamente 1, 1).
Non archiviare i conteggi in una tabella: utilizzare una VISTA per questo in modo che il numero possa essere generato in base ai dati esistenti al momento dell'esecuzione.
- Non userei il nome utente come ID principale. Vorrei fare un ID numerico con autoincrement
- Vorrei usare quel nuovo ID nella tabella delle relazioni con una chiave univoca sui 2 campi
Anche se non è nella domanda, potresti voler avere un ID utente che è la chiave primaria, altrimenti sarà difficile se l'utente è autorizzato a cambiare il suo nome utente o far sapere a certe persone che non puoi cambiare il tuo nome utente.
Rendi la tabella unita un vincolo univoco su userid e entryid. In questo modo il database impone che vi sia un solo commento / voce / utente.
Sarebbe utile se si specifica un database, tra l'altro.
Sembra che tu voglia garantire che l'insieme di commenti sia univoco rispetto a nome utente
X post_id
. Puoi farlo usando un vincolo univoco o se il tuo sistema di database non lo supporta esplicitamente, con un indice che fa lo stesso. Ecco alcuni SQL che lo esprimono:
CREATE TABLE users (
username VARCHAR(10) PRIMARY KEY,
-- any other data ...
);
CREATE TABLE posts (
post_id INTEGER PRIMARY KEY,
-- any other data ...
);
CREATE TABLE comments (
username VARCHAR(10) REFERENCES users(username),
post_id INTEGER REFERENCES posts(post_id),
-- any other data ...
UNIQUE (username, post_id) -- Here's the important bit!
);