Gestire una singola informazione
Supponendo che, nel tuo dominio aziendale,
- un utente può avere zero-uno-o-molti amici ;
- un amico deve prima essere registrato come utente ; e
- cercherai e / o aggiungerai, e / o rimuoverai e / o modificherai singoli valori di un Elenco di amici ;
quindi ogni dato specifico raccolto nella Friendlist_IDs
colonna multivalore rappresenta un'informazione separata che ha un significato molto esatto. Pertanto, detta colonna
- comporta un gruppo adeguato di vincoli espliciti e
- i suoi valori hanno il potenziale di essere manipolati individualmente per mezzo di diverse operazioni relazionali (o loro combinazioni).
Risposta breve
Di conseguenza, dovresti conservare ciascuno dei Friendlist_IDs
valori in (a) una colonna che accetta esclusivamente un valore unico per riga in (b) una tabella che rappresenta il tipo di associazione a livello concettuale che può avere luogo tra Utenti , ovvero un'amicizia, come Esemplificerò nelle seguenti sezioni:
In questo modo, sarai in grado di gestire (i) detta tabella come relazione matematica e (ii) detta colonna come attributo di relazione matematica - tanto quanto MySQL e il suo dialetto SQL lo consentono, ovviamente—.
Perché?
Perché il modello relazionale di dati , creato dal Dr. E. F. Codd , richiede di avere tabelle composte da colonne che contengano esattamente un valore del dominio o tipo applicabile per riga; pertanto, dichiarare una tabella con una colonna che può contenere più di un valore del dominio o del tipo in questione (1) non rappresenta una relazione matematica e (2) non consentirebbe di ottenere i vantaggi proposti nel suddetto quadro teorico.
Modellare le amicizie tra utenti : definire prima le regole dell'ambiente aziendale
Consiglio vivamente di iniziare a modellare un database che delimita - prima di ogni altra cosa - lo schema concettuale corrispondente in virtù della definizione delle pertinenti regole commerciali che, tra gli altri fattori, devono descrivere i tipi di interrelazioni esistenti tra i diversi aspetti di interesse, vale a dire , i tipi di entità applicabili e le loro proprietà ; per esempio:
- Un utente è identificato principalmente dal suo ID utente
- Un utente è alternativamente identificato dalla combinazione della sua FirstName , Cognome , Sesso , e Data di nascita
- Un utente viene alternativamente identificato dal suo nome utente
- Un utente è il richiedente di amicizie zero-uno-o-molte
- Un utente è il destinatario di amicizie zero-uno-o-molte
- Un'amicizia è principalmente identificato dalla combinazione della sua RequesterId e la sua AddresseeId
Diagramma IDEF1X dell'esposizione
In questo modo, sono stato in grado di derivare il diagramma IDEF1X 1 mostrato in Figura 1 , che integra la maggior parte delle regole precedentemente formulate:
Come illustrato, il richiedente e il destinatario sono denotazioni che esprimono i ruoli svolti dagli utenti specifici che prendono parte a una determinata amicizia .
Ciò premesso, il tipo di entità Amicizia rappresenta un tipo di associazione con un rapporto di cardinalità molti-a-molti (M: N) che può comportare diverse occorrenze dello stesso tipo di entità, ovvero Utente . In quanto tale, è un esempio del classico costrutto noto come "distinta materiali" o "esplosione delle parti".
1 Integration Definition for Information Modeling ( IDEF1X ) è una tecnica altamente raccomandabile che è stata stabilita come standard nel dicembre 1993 dal National Institute of Standards and Technology (NIST)degli Stati Uniti. È solidamente basato su (a) il materiale teorico iniziale creato dall'unico creatore del modello relazionale, cioè il Dr. EF Codd ; su (b) lavisione entità-relazione dei dati, sviluppata dal Dr. PP Chen ; e anche su (c) la tecnica di progettazione del database logico, creata da Robert G. Brown.
Progettazione logica illustrativa SQL-DDL
Quindi, dal diagramma IDEF1X presentato sopra, dichiarare una disposizione DDL come quella che segue è molto più "naturale":
-- You should determine which are the most fitting
-- data types and sizes for all the table columns
-- depending on your business context characteristics.
-- At the physical level, you should make accurate tests
-- to define the mostconvenient INDEX strategies based on
-- the pertinent query tendencies.
-- As one would expect, you are free to make use of
-- your preferred (or required) naming conventions.
CREATE TABLE UserProfile ( -- Represents an independent entity type.
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATE NOT NULL,
GenderCode CHAR(3) NOT NULL,
Username CHAR(20) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
FirstName,
LastName,
GenderCode,
BirthDate
),
CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- Single-column ALTERNATE KEY.
);
CREATE TABLE Friendship ( -- Stands for an associative entity type.
RequesterId INT NOT NULL,
AddresseeId INT NOT NULL, -- Fixed with a well-delimited data type.
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Friendship_PK PRIMARY KEY (RequesterId, AddresseeId), -- Composite PRIMARY KEY.
CONSTRAINT FriendshipToRequester_FK FOREIGN KEY (RequesterId)
REFERENCES UserProfile (UserId),
CONSTRAINT FriendshipToAddressee_FK FOREIGN KEY (AddresseeId)
REFERENCES UserProfile (UserId)
);
In questo modo:
- ogni tabella di base rappresenta un tipo di entità individuale;
- ogni colonna rappresenta una sola proprietà del rispettivo tipo di entità;
- uno specifico tipo di dati un è fissato per ogni colonna al fine di garantire che tutti i valori che contiene appartengono a una particolare e ben definito insieme , sia esso INT, DATETIME, CHAR, ecc .; e
- più vincoli b sono configurati (in modo dichiarativo) al fine di garantire che le asserzioni sotto forma di righe conservate in tutte le tabelle soddisfino le regole aziendali determinate nello schema concettuale.
Vantaggi di una colonna a valore singolo
Come dimostrato, è possibile, ad esempio:
Sfrutta l' integrità referenziale applicata dal sistema di gestione del database (DBMS per brevità) per la Friendship.AddresseeId
colonna, dal momento che vincolandola come FOREIGN KEY (FK per brevità) che fa un riferimento alla UserProfile.UserId
colonna garantisce che ogni valore punta a una riga esistente .
Crea un PRIMARY KEY composito (PK) composto dalla combinazione di colonne (Friendship.RequesterId, Friendship.AddresseeId)
, contribuendo a distinguere elegantemente tutte le righe INSERITE e, naturalmente, proteggendo la loro unicità .
Ovviamente, ciò significa che l'allegato di una colonna aggiuntiva per i valori surrogati assegnati dal sistema (ad esempio, uno impostato con la proprietà IDENTITY in Microsoft SQL Server o con l' attributo AUTO_INCREMENT in MySQL) e l'indice di assistenza è del tutto superfluo .
Limitare i valori conservati Friendship.AddresseeId
a un preciso tipo di dati c (che dovrebbe corrispondere, ad esempio, a quello stabilito per UserProfile.UserId
, in questo caso INT), lasciando che il DBMS si occupi della relativa validazione automatica .
Questo fattore può anche aiutare a (a) utilizzare le corrispondenti funzioni del tipo incorporato e (b) ottimizzare l' utilizzo dello spazio su disco .
Ottimizza il recupero dei dati a livello fisico configurando INDICE subordinati piccoli e veloci per la Friendship.AddresseeId
colonna, poiché questi elementi fisici possono aiutare sostanzialmente ad accelerare le query che coinvolgono detta colonna.
Certamente, puoi, ad esempio, creare un INDICE a colonna singola per Friendship.AddresseeId
solo, uno a più colonne che comprende Friendship.RequesterId
e Friendship.AddresseeId
, o entrambi.
Evita la complessità inutile introdotta dalla "ricerca" di valori distinti che vengono raccolti insieme nella stessa colonna (molto probabilmente duplicati, digitati in modo errato, ecc.), Un corso d'azione che alla fine rallenterebbe il funzionamento del tuo sistema, perché ricorrere a metodi non relazionali dispendiosi in termini di risorse e di tempo per svolgere tale compito.
Pertanto, ci sono molte ragioni che richiedono di analizzare attentamente l'ambiente aziendale rilevante al fine di contrassegnare con precisione il tipo d di ogni colonna della tabella.
Come spiegato, il ruolo svolto dal progettista del database è fondamentale per sfruttare al meglio (1) i vantaggi a livello logico offerti dal modello relazionale e (2) i meccanismi fisici forniti dal DBMS preferito.
a , b , c , d Evidentemente, quando si lavora con piattaforme SQL (ad esempio, Firebird e PostgreSQL ) che supportano la creazione di DOMAIN (una caratteristica relazionale distintiva), è possibile dichiarare colonne che accettano solo valori che appartengono ai rispettivi (opportunamente vincolati e talvolta condiviso) DOMINI.
Uno o più programmi applicativi che condividono il database in esame
Quando si deve impiegare arrays
nel codice del programma applicativo (s) accesing il database, è semplicemente bisogno di recuperare il set di dati in questione (s) in pieno e poi “legare” lo (li) per la struttura del codice in materia o eseguire il processi che devono essere associati.
Ulteriori vantaggi delle colonne a valore singolo: le estensioni della struttura del database sono molto più semplici
Un altro vantaggio di mantenere il AddresseeId
punto dati nella sua colonna riservata e tipizzata correttamente è che facilita notevolmente l'estensione della struttura del database, come illustrerò di seguito.
Progressione dello scenario: integrazione del concetto di status di amicizia
Poiché Friendships può evolversi nel tempo, potresti dover tenere traccia di tale fenomeno, quindi dovresti (i) espandere lo schema concettuale e (ii) dichiarare alcune altre tabelle nel layout logico. Quindi, cerchiamo di organizzare le prossime regole aziendali per delineare le nuove incorporazioni:
- Un'amicizia detiene uno-a-molti FriendshipStatuses
- Un FriendshipStatus è principalmente identificato dalla combinazione di RequesterId , AddresseeId e SpecifiedDateTime
- Un utente specifica zero-one-o-many FriendshipStatuses
- Uno stato classifica zero-one-o-many FriendshipStatuses
- Uno stato è identificato principalmente dal suo StatusCode
- Uno stato viene alternativamente identificato dal suo nome
Diagramma IDEF1X esteso
Successivamente, il precedente diagramma IDEF1X può essere esteso al fine di includere i nuovi tipi di entità e i tipi di interrelazione sopra descritti. Un diagramma che raffigura gli elementi precedenti associati a quelli nuovi è presentato in Figura 2 :
Aggiunte di strutture logiche
Successivamente, possiamo allungare il layout DDL con le seguenti dichiarazioni:
--
CREATE TABLE MyStatus ( -- Denotes an independent entity type.
StatusCode CHAR(1) NOT NULL,
Name CHAR(30) NOT NULL,
--
CONSTRAINT MyStatus_PK PRIMARY KEY (StatusCode),
CONSTRAINT MyStatus_AK UNIQUE (Name) -- ALTERNATE KEY.
);
CREATE TABLE FriendshipStatus ( -- Represents an associative entity type.
RequesterId INT NOT NULL,
AddresseeId INT NOT NULL,
SpecifiedDateTime DATETIME NOT NULL,
StatusCode CHAR(1) NOT NULL,
SpecifierId INT NOT NULL,
--
CONSTRAINT FriendshipStatus_PK PRIMARY KEY (RequesterId, AddresseeId, SpecifiedDateTime), -- Composite PRIMARY KEY.
CONSTRAINT FriendshipStatusToFriendship_FK FOREIGN KEY (RequesterId, AddresseeId)
REFERENCES Friendship (RequesterId, AddresseeId), -- Composite FOREIGN KEY.
CONSTRAINT FriendshipStatusToMyStatus_FK FOREIGN KEY (StatusCode)
REFERENCES MyStatus (StatusCode),
CONSTRAINT FriendshipStatusToSpecifier_FK FOREIGN KEY (SpecifierId)
REFERENCES UserProfile (UserId)
);
Di conseguenza, ogni volta che lo stato di una determinata amicizia deve essere aggiornato, gli utenti devono solo INSERIRE una nuova FriendshipStatus
riga, contenente:
l'idoneo RequesterId
e i AddresseeId
valori — presi dalla Friendship
riga relativa— ;
il nuovo e significativo StatusCode
valore - tratto da MyStatus.StatusCode
-;
l'esatto istante di INSERTion, ovvero —preferibilmente SpecifiedDateTime
usando una funzione server in modo da poterlo recuperare e conservare in modo affidabile—; e
il SpecifierId
valore che indicherebbe il rispettivo UserId
che ha inserito il nuovo FriendshipStatus
nel sistema —dealmente, con l'aiuto delle strutture delle tue app —.
In tal senso, supponiamo che la MyStatus
tabella includa i seguenti dati —con valori PK che sono (a) utenti finali, programmatori di app e DBA-friendly e (b) piccoli e veloci in termini di byte a livello di implementazione fisica -:
+ ------------ + ----------- +
| StatusCode | Nome |
+ ------------ + ----------- +
| R | Richiesto |
+ ------------ + ----------- +
| A | Accettato |
+ ------------ + ----------- +
| D | Rifiutato |
+ ------------ + ----------- +
| B | Bloqued |
+ ------------ + ----------- +
Pertanto, la FriendshipStatus
tabella può contenere dati come mostrato di seguito:
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| RequesterId | AddresseeId | SpecifiedDateTime | StatusCode | SpecifierId |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 01-04-2016 16: 58: 12.000 | R | 1750 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 02-04-2016 09: 12: 05.000 | A | 1748 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 04-04-2016 10: 57: 01.000 | B | 1750 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 07-04-2016 07: 33: 08.000 | R | 1748 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 08-04-2016 12: 12: 09.000 | A | 1750 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
Come puoi vedere, si può dire che la FriendshipStatus
tabella ha lo scopo di comprendere una serie temporale .
Post pertinenti
Potresti anche essere interessato a:
- Questa risposta in cui suggerisco un metodo di base per affrontare una relazione molti-a-molti comune tra due diversi tipi di entità.
- Il diagramma IDEF1X mostrato nella Figura 1 che illustra questa altra risposta . Presta particolare attenzione ai tipi di entità denominati Matrimonio e Progenia , perché sono altri due esempi di come gestire il "Problema di esplosione delle parti".
- Questo post presenta una breve deliberazione sul possesso di diverse informazioni all'interno di una singola colonna.