Il mio insegnante t-sql ci ha detto che nominare la nostra colonna PK "Id" è considerata una cattiva pratica senza ulteriori spiegazioni.
Perché la denominazione di una colonna PK della tabella "Id" è considerata una cattiva pratica?
Il mio insegnante t-sql ci ha detto che nominare la nostra colonna PK "Id" è considerata una cattiva pratica senza ulteriori spiegazioni.
Perché la denominazione di una colonna PK della tabella "Id" è considerata una cattiva pratica?
Risposte:
Sto per uscire e dirlo: non è davvero una cattiva pratica (e anche se lo è, non è poi così male).
Potresti argomentare (come ha sottolineato Chad ) che può mascherare errori come nella seguente query:
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
ma questo può essere facilmente mitigato non usando piccoli alias per i nomi delle tabelle:
SELECT *
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.ManufacturerId
JOIN models
ON models.Id = cars.ModelId
JOIN colors
ON manufacturer.Id = cars.ColorId
La pratica di usare SEMPRE le abbreviazioni di 3 lettere mi sembra molto peggio che usare il nome della colonna id
. (Caso in questione: chi abbrevia effettivamente il nome della tabella cars
con l'abbreviazione car
? A che fine serve?)
Il punto è: essere coerenti. Se la tua azienda utilizza Id e in genere commetti l'errore sopra, prendi l'abitudine di utilizzare nomi di tabella completi. Se la tua azienda vieta la colonna ID, prendi il passo e usa la convenzione di denominazione che preferisce.
Concentrati sull'apprendimento di cose che sono REALMENTE cattive pratiche (come più query secondarie correlate nidificate) piuttosto che rimuginare su problemi come questo. Il problema di nominare le tue colonne "ID" è più vicino ad essere una questione di gusti che a essere una cattiva pratica.
NOTA PER GLI EDITORI: l'errore in questa query è intenzionale e viene utilizzato per indicare un punto. Si prega di leggere la risposta completa prima della modifica.
cars
-> car
. Grazie a Dio - mi hai salvato le dita). Non leggere troppo in profondità.
cars
e manufacturer
. Uno è plurale, l'altro no. Se la gente vuole scegliere nel db, questa è la cattiva pratica che dovrebbe essere presa in considerazione.
Perché quando si dispone di una tabella con una chiave esterna non è possibile denominare la chiave esterna "Id". Hai nome tabella TableId
E poi il tuo join sembra
SELECT * FROM cars c JOIN manufacturer m ON m.Id = c.ManufacturerId
E idealmente, la tua condizione dovrebbe avere lo stesso nome di campo su ciascun lato
SELECT * FROM cars c JOIN manufacturer m ON m.ManufacturerId = c.ManufacturerId
Quindi, anche se sembra ridondante nominare l'ID come ManufacturerId, è meno probabile che tu abbia degli errori nelle condizioni di partecipazione, poiché gli errori diventano evidenti.
Sembra semplice, ma quando ti unisci a più tavoli, diventa più probabile che tu commetta un errore, trova quello qui sotto ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
Considerando che con una corretta denominazione, l'errore sporge ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.ManufacturerId = car.ManufacturerId
JOIN models mod
ON mod.ModelId = car.ModelId
JOIN colors col
ON mfg.ManufacturerId = car.ColorId
Un altro motivo per cui denominarli Id è "errato" è che quando si richiedono informazioni da più tabelle, è necessario rinominare le colonne Id in modo da poterle distinguere.
SELECT manufacturer.Id as 'ManufacturerId'
,cars.Id as 'CarId'
--etc
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.Id
Con nomi precisi questo è meno un problema
SELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId
. Ho usato id
per anni e non ho mai trovato quello che hai descritto come un vero problema.
SELECT manufacturer.id FROM ...
. Ogni difficoltà derivante id
può essere superata molto facilmente, rendendola semplicemente una questione di gusti.
La libreria ActiveRecord di Ruby e GORM di Groovy usano "id" per la chiave surrogata per impostazione predefinita. Mi piace questa pratica. La duplicazione del nome della tabella in ciascun nome di colonna è ridondante, noiosa da scrivere e più noiosa da leggere.
I nomi di colonne comuni o chiave come "Nome" o "Id" devono essere preceduti da TableName.
Elimina l'ambiguità, più facile da cercare, significa molto meno alias di colonna quando sono necessari entrambi i valori "Id".
Una colonna o chiave non utilizzata meno utilizzata o di controllo (ad esempio LastUpdatedDateTime) non ha importanza
name
e id
? Perché non avere ogni colonna con il prefisso con il nome della sua tabella? Sembra arbitrario scegliere quei due nomi per imporre un prefisso. Concettualmente, è necessario disporre della tabella per avere comunque il contesto di una colonna. Perché non usare semplicemente il nome della tabella per chiarire la query: Person.Name, Animal.Name, Part.Name, ...
Questo thread è morto, ma vorrei aggiungere che IMO non usando Id
è una cattiva pratica. La Id
colonna è speciale; è la chiave primaria. Qualsiasi tabella può avere un numero qualsiasi di chiavi esterne, ma può avere solo una chiave primaria. In un database in cui vengono chiamate tutte le chiavi primarie Id
, non appena si guarda la tabella si conosce esattamente quale colonna è la chiave primaria.
Credetemi, da mesi ho passato tutto il giorno ogni giorno a lavorare in molti grandi database (Salesforce) e la cosa migliore che posso dire sugli schemi è che ogni tabella ha una chiave primaria chiamata Id
. Posso assicurarti che non mi confondo assolutamente sull'unire una chiave primaria a una chiave esterna perché viene chiamato PK Id
. Un'altra cosa che la gente non ha menzionato è che le tabelle possono avere nomi lunghi e sciocchi Table_ThatDoesGood_stuff__c
; quel nome è abbastanza brutto perché l'architetto ha avuto i postumi di una sbornia la mattina ha pensato a quella tabella, ma ora mi stai dicendo che è una cattiva pratica non chiamare la chiave primaria Table_ThatDoesGood_stuff__cId
(ricordando che i nomi delle colonne SQL non sono in generale sensibili al maiuscolo / minuscolo).
Ad essere onesti, i problemi con la maggior parte delle persone che insegnano la programmazione informatica sono che non scrivono una riga di codice di produzione da anni, se non mai, e non hanno idea di cosa faccia effettivamente un ingegnere del software funzionante. Aspetta di iniziare a lavorare e poi decidi cosa pensi sia una buona idea o no.
Non la considero una cattiva pratica. La coerenza è re, come al solito.
Penso che sia tutto basato sul contesto. Nel contesto della tabella a sé stante, "id" significa esattamente ciò che ti aspetti, un'etichetta che aiuti a identificarlo in modo univoco rispetto ad altri che potrebbero altrimenti essere (o apparire) identici.
Nel contesto dei join, è tua responsabilità costruire i join in modo tale da renderli leggibili a te e al tuo team. Così come è possibile rendere le cose difficili con frasi o denominazioni scadenti, è altrettanto possibile costruire una query significativa con un uso efficace di alias e persino commenti.
Allo stesso modo una classe Java chiamata 'Foo' non ha le sue proprietà precedute da 'Foo', non sentirti obbligato a mettere in prefisso i tuoi ID tabella con i nomi delle tabelle. Di solito è chiaro nel contesto quale sia l'ID a cui si fa riferimento.
BOOM, risposta alla domanda.
Ora vai a dire al tuo insegnante che SO pratica una cattiva progettazione del database.
PostTypeId -> PostTypes.Id
; AcceptedAnswerId -> Answers.Id
; OwnerUserId -> Users.Id
. Perché una pratica così facile dovrebbe essere considerata "cattiva"?
Rende difficile (e confuso) eseguire un join naturale sul tavolo, quindi sì, è male se non molto male.
Natural Join è un antico manufatto di SQL Lore (ovvero l'algebra relazionale) che potresti aver visto uno di questi: ⋈ forse in un libro di database. Quello che voglio dire è che Natrual Join non è una nuova idea SQL confusa, anche se sembrava che ci fosse voluta un'eternità per l'implementazione da parte di DBMS, quindi non è una nuova idea complicata per implementarla, potrebbe anche essere irragionevole ignorarla la sua esistenza al giorno d'oggi.
Bene, se assegni un nome a tutto l'ID della tua chiave primaria, perdi la facilità e la semplicità del join naturale. select * from dudes natural join cars
dovrà essere scritto select * from dudes inner join cars where cars.dudeid = dudes.id
o select * from dudes inner join cars where dudes.carid = cars.id
. Se sei in grado di fare un join naturale, puoi ignorare qual è la relazione in realtà, che, credo, è piuttosto fantastica.
C'è una situazione in cui attaccare "ID" su ogni tabella non è la migliore idea: la USING
parola chiave, se è supportata. Lo usiamo spesso in MySQL.
Ad esempio, se hai fooTable
con colonna fooTableId
e barTable
con chiave esterna fooTableId
, le tue query possono essere costruite come tali:
SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)
Non solo salva la digitazione, ma è molto più leggibile rispetto all'alternativa:
SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)
USING
parola chiave è supportata dal database postgres / mysql / sqlite, significa meno digitazioni che alcune delle altre risposte elencano come motivo per l'uso id
, e infine secondo la mia opinione soggettiva è più leggibile.
Perché non chiedere semplicemente al tuo insegnante?
Pensa a questo, quando tutte le colonne PK delle tue tabelle vengono denominate ID
, il loro uso come chiavi esterne è un incubo.
I nomi delle colonne devono essere semanticamente significativi. ID
è generico.
id
da solo non significa nulla, specialmente nel contesto di una chiave esterna per un'altra tabella. Questo non ha nulla a che fare con classes
tutto e ha a che fare con una buona progettazione di base del database relazionale fondamentale.
table.id
è un modo perfettamente accettabile di riferirsi a un id
campo. Prefisso il nome del campo con il nome della tabella è ridondante.
L'ID è errato per i seguenti motivi:
Se esegui molte query sui rapporti devi sempre aliasare le colonne se vuoi vederle entrambe. Quindi diventa una perdita di tempo quando potresti nominarlo correttamente per cominciare. Queste query complesse sono abbastanza difficili (scrivo query che possono essere lunghe centinaia di righe) senza l'onere aggiuntivo di eseguire lavori inutili.
È soggetto a causare errori di codice. Se usi un database che consente l'uso del join naturale (non che penso che dovresti mai usare, ma quando le funzionalità sono disponibili qualcuno li utilizzerà), ti unirai alla cosa sbagliata se ottieni uno sviluppatore che lo utilizza.
Se si stanno copiando i join per creare una query complessa, è facile dimenticare di cambiare l'alias con quello desiderato e ottenere un join errato. Se ogni ID prende il nome dalla tabella in cui si trova, di solito si verifica un errore di sintassi. È anche più facile individuare se l'unione in una query complessa non è corretta se il nome pPK e il nome FK corrispondono.
ID
non mi convincono affatto.
Ci sono alcune risposte che si avvicinano a ciò che considererei il motivo più importante per non usare "id" come nome della colonna per la chiave primaria in una tabella: coerenza e ridotta ambiguità.
Tuttavia, per me il vantaggio chiave è realizzato dal programmatore di manutenzione, in particolare uno che non è stato coinvolto nello sviluppo originale. Se hai usato il nome "PersonID" per l'ID nella tabella Person e hai sempre usato quel nome come chiave esterna, è banale scrivere una query sullo schema per scoprire quali tabelle hanno PersonID senza dover dedurre quel "PersonID" è il nome usato quando è una chiave esterna. Ricorda, giusto o sbagliato, le relazioni con le chiavi esterne non sono sempre applicate in tutti i progetti.
Esiste un caso limite in cui una tabella potrebbe aver bisogno di avere due chiavi esterne nella stessa tabella, ma in questi casi inserirò il nome della chiave originale come nome del suffisso per la colonna, quindi una corrispondenza con caratteri jolly,% PersonID, potrebbe facilmente trovare anche questi casi.
Sì, gran parte di questo potrebbe essere realizzato da uno standard di avere "id" e sapendo di usarlo sempre come "tableNameID", ma ciò richiede sia sapere che la pratica è in atto sia che, a seconda degli sviluppatori originali, seguire con meno pratica standard intuitiva.
Mentre alcune persone hanno sottolineato che per scrivere i nomi delle colonne più lunghe sono necessari alcuni tasti in più, direi che scrivere il codice è solo una piccola parte della vita attiva del programma. Se l'obiettivo era salvare le sequenze di tasti dello sviluppatore, i commenti non dovrebbero mai essere scritti.
Come qualcuno che ha trascorso molti anni a gestire progetti di grandi dimensioni con centinaia di tabelle, preferirei fortemente nomi coerenti per una chiave su più tabelle.
Companies
tabella abbia 2 chiavi esterne in una Persons
tabella. Uno rappresenta il presidente dell'azienda; l'altro rappresenta il tesoriere dell'azienda. Chiamereste davvero le colonne PersonID1
e PersonID2
? Sarebbe molto più descrittivo chiamarli PresidentID
e TreasurerID
. Trovo molto più facile da leggere inner join Person AS Presidents ON Company.PresidentID = Presidents.ID
rispetto ainner join Person AS Person1 ON Company.PersonID1 = Person1.PersonID
CompanyOfficer
o una CompanyPerson
tabella che consente una relazione molti-a-molti con Company
e Person
con informazioni aggiuntive sulla natura della relazione. Se dovessi implementarlo all'interno della Company
tabella, utilizzerei i nomi delle colonne PresidentPersonID
e TreasurerPersonID
per preservare la parte * PersonID del nome durante l'aggiunta del descrittore aggiuntivo. inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
La pratica di utilizzare Id come campo chiave primaria porta alla pratica in cui l'id viene aggiunto a ogni tabella. Molte tabelle hanno già informazioni uniche che identificano in modo univoco un record. Usa QUESTO come chiave primaria e non un campo ID che aggiungi a ogni singola tabella. Questa è una delle basi dei database relazionali.
Ed è per questo che usare id è una cattiva pratica: id spesso non è solo un aumento automatico delle informazioni.
considerare le seguenti tabelle:
PK id | Countryid | Countryname
1 | 840 | United States
2 | 528 | the Netherlands
Ciò che non va in questa tabella è che consente all'utente di aggiungere un'altra riga: gli Stati Uniti, con il codice paese 840. Ha appena rotto l'integrità relazionale. Ovviamente puoi applicare l'univocità su singole colonne oppure puoi semplicemente usare una chiave primaria già disponibile:
PK Countryid | Countryname
840 | United States
528 | the Netherlands
In questo modo usi le informazioni che hai già come chiave primaria, che è al centro della progettazione di database relazionali.
Non penso che sia una cattiva pratica se usato correttamente. È comune avere un campo ID a incremento automatico chiamato "ID" che non si deve mai toccare e utilizzare un identificatore più amichevole per l'applicazione. Scrivere codice può essere un po 'complicato, from tableA a inner join tableB b on a.id = b.a_id
ma quel codice può essere nascosto.
Come preferenza personale tendo a aggiungere l'ID al nome dell'entità, ma non vedo un vero problema con il solo utilizzo Id
se è gestito interamente dal database.
L'identità è abbastanza comune, che non penso che confonderebbe nessuno. Avrai sempre voglia di conoscere il tavolo. Inserire i nomi dei campi nel codice di produzione senza includere una tabella / alias è una cattiva pratica. Se sei troppo preoccupato di poter digitare rapidamente query ad hoc, sei da solo.
Spero solo che nessuno sviluppi un database sql in cui ID sia una parola riservata.
CREATE TABLE CAR (ID);
Si prende cura del nome del campo, della chiave primaria e degli incrementi automatici di 1 a partire da 1 tutto in un bel pacchetto di 2 caratteri. Oh, e l'avrei chiamato CARS ma se vogliamo risparmiare sui tasti e chi crede davvero che un tavolo chiamato CAR ne avrà solo uno?
Car
rappresenta un punto in Table
cui ognuno Row
rappresenta un singolo Car
. Richiamare Cars
cambia il semantico e mostra una completa mancanza di comprensione dei principi di base della teoria relazionale formale. Rails è un ottimo esempio di qualcuno che sapeva abbastanza per essere pericoloso .
Questa domanda è stata ripetutamente ribadita, ma ho pensato che avrei aggiunto anche la mia opinione.
Uso id per indicare che si tratta dell'identificatore di ogni tabella, quindi quando mi unisco a una tabella e ho bisogno della chiave primaria, mi unisco automaticamente alla chiave primaria.
Il campo ID è un autoincremento, senza segno (nel senso che non devo mai impostare il suo valore e non può essere negativo)
Per le chiavi esterne, uso tablenameid (di nuovo una questione di stile), ma la chiave primaria a cui mi unisco è il campo id della tabella, quindi la coerenza significa che posso sempre controllare facilmente le query
l'id è anche breve e dolce
Convenzione aggiuntiva: utilizzare le lettere minuscole per tutti i nomi di tabelle e colonne, quindi non sono stati rilevati problemi dovuti al caso
Un'altra cosa da considerare è che se il nome della chiave primaria è diverso dal nome della chiave esterna, non è possibile utilizzare determinati strumenti di terze parti.
Ad esempio, non sarebbe possibile caricare lo schema in uno strumento come Visio e farlo produrre ERD accurati.
Trovo che le persone qui trattino praticamente ogni aspetto, ma voglio aggiungere che "id" non è e non dovrebbe essere letto come "identificatore", è più un "indice" e sicuramente non indica o descrive l'identità della riga. (Potrei aver usato una formulazione sbagliata qui, per favore correggimi se l'ho fatto)
È più o meno come le persone leggono i dati della tabella e come scrivono il loro codice. Personalmente e molto probabilmente questo è il modo più popolare che vedo più frequentemente è che i programmatori scrivono il riferimento completo come table.id
, anche se non hanno bisogno di fare sindacati o / e join. Per esempio:
SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>
In questo modo puoi tradurlo in inglese come "Dammi il colore e il modello di quella macchina che è numerata come". e non come "Dammi il colore e il modello di quell'auto identificata come numero". L'ID non rappresenta l'auto in alcun modo, è solo l'indice dell'auto, un numero di serie se lo desideri. Proprio come quando vuoi prendere il terzo elemento da un array.
Quindi per riassumere ciò che volevo aggiungere è che è solo una questione di preferenza e il modo descritto di leggere SQL è il più popolare.
Tuttavia, ci sono alcuni casi in cui questo non viene utilizzato, come (un esempio molto più raro) quando l'ID è una stringa che sta veramente descrivendo. Ad esempio id = "RedFordMustang1970"
o qualcosa di simile. Spero davvero di poterlo spiegare almeno per avere l'idea.