Domanda

Mi chiedevo le opinioni delle persone sulla denominazione delle colonne ID nelle tabelle del database.

Se avessi una tabella chiamata Fatture con una chiave primaria di una colonna identità, chiamerei quella colonna InvoiceID in modo da non essere in conflitto con altre tabelle ed è ovvio che cos'è.

Dove sono attualmente workind hanno chiamato tutti ID colonne ID.

Quindi farebbero quanto segue:

Select  
    i.ID 
,   il.ID 
From
    Invoices i
    Left Join InvoiceLines il
        on i.ID = il.InvoiceID

Ora, vedo alcuni problemi qui:
1. Dovresti aliasare le colonne su select
2. ID = InvoiceID non si adatta al mio cervello
3. Se non hai aliasato le tabelle e fatto riferimento a InvoiceID è ovvio su quale tabella si trova?

Quali sono i pensieri degli altri sull'argomento?

È stato utile?

Soluzione

ID è un Antipattern SQL. Vedi http: // www.amazon.com/s/ref=nb_sb_ss_i_1_5?url=search-alias%3Dstripbooks&field-keywords=sql+antipatterns&sprefix=sql+a

Se hai molte tabelle con ID come ID, rendi i rapporti molto più difficili. Oscura il significato e rende le letture complesse più difficili da leggere, oltre a richiedere l'utilizzo di alias per differenziare il report stesso.

Inoltre, se qualcuno è abbastanza sciocco da utilizzare un join naturale in un database in cui sono disponibili, ti unirai ai record errati.

Se si desidera utilizzare la sintassi USING consentita da alcuni dbs, non è possibile utilizzare ID.

Se usi ID puoi facilmente finire con un join errato se ti capita di copiare la sintassi del join (non dirmi che nessuno lo fa mai!) e dimentica di cambiare l'alias nella condizione di join.

Quindi ora hai

select t1.field1, t2.field2, t3.field3
from table1 t1 
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t1.id = t3.table2id

quando intendevi

select t1.field1, t2.field2, t3.field3 
from table1 t1 
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t2.id = t3.table2id

Se si utilizza tablenameID come campo ID, questo tipo di errore accidentale è molto meno probabile che accada e molto più facile da trovare.

Altri suggerimenti

Ho sempre preferito ID a TableName + ID per la colonna ID e quindi TableName + ID per una chiave esterna. In questo modo tutte le tabelle hanno lo stesso nome per il campo ID e non esiste una descrizione ridondante. Questo mi sembra più semplice perché tutte le tabelle hanno lo stesso nome del campo chiave principale.

Per quanto riguarda l'unione delle tabelle e non sapere quale campo Id appartiene a quale tabella, a mio avviso la query dovrebbe essere scritta per gestire questa situazione. Dove lavoro, preferiamo sempre i campi che usiamo in un'istruzione con l'alias table / table.

C'è stata una rissa da secchione su questa cosa nella mia compagnia negli ultimi tempi. L'avvento di LINQ ha reso il modello ridondante tablename + ID ancora più ovviamente sciocco ai miei occhi. Penso che le persone più ragionevoli diranno che se stai scrivendo a mano il tuo SQL in modo tale che devi specificare i nomi delle tabelle per differenziare FK , allora non è solo un risparmio sulla digitazione, ma aggiunge chiarezza sul tuo SQL per usare solo l'ID in quanto puoi vedere chiaramente quale è PK e quale è FK .

per es.

DA Dipendenti e     LEFT JOIN Clienti c ON e.ID = c.EmployeeID

mi dice non solo che i due sono collegati, ma qual è il PK e quale è il FK . Mentre nel vecchio stile sei costretto a guardare o sperare che siano stati nominati bene.

Utilizziamo InvoiceID , non ID . Rende le query più leggibili - quando vedi ID da solo potrebbe significare qualsiasi cosa, specialmente quando alias la tabella su i .

Sono d'accordo con Keven e alcune altre persone che il PK per un tavolo dovrebbe essere semplicemente ID e le chiavi esterne elencano OtherTable + Id.

Tuttavia, desidero aggiungere una ragione che recentemente ha dato più peso a questo argomento.

Nella mia posizione attuale stiamo impiegando il framework di entità usando la generazione POCO. Utilizzando la convenzione di denominazione standard di Id, il PK consente l'ereditarietà di una classe di base poco con convalida e tale per le tabelle che condividono un insieme di nomi di colonne comuni. L'uso di Tablename + Id come PK per ciascuna di queste tabelle distrugge la possibilità di utilizzare una classe base per queste.

Solo qualche spunto di riflessione.

Non è molto importante, è probabile che si verifichino problemi simili in tutte le convenzioni di denominazione.

Ma è importante essere coerenti, quindi non è necessario guardare le definizioni delle tabelle ogni volta che si scrive una query.

La mia preferenza è anche ID per chiave primaria e TableNameID per chiave esterna. Mi piace anche avere una colonna " name " nella maggior parte delle tabelle in cui tengo l'identificatore leggibile dall'utente (ovvero il nome :-)) della voce. Questa struttura offre una grande flessibilità nell'applicazione stessa, posso gestire le tabelle in massa, allo stesso modo. Questa è una cosa molto potente. Di solito un software OO è costruito sopra il database, ma il set di strumenti OO non può essere applicato perché il db stesso non lo consente. Avere l'id e il nome delle colonne non è ancora molto buono, ma è un passaggio.

  

Seleziona
      i.ID, il.ID Da       Fatture i       Sinistra Iscriviti a InvoiceLines il           su i.ID = il.InvoiceID

Perché non posso farlo?

Select  
    Invoices.ID 
,   InvoiceLines.ID 
From
    Invoices
    Left Join InvoiceLines
        on Invoices.ID = InvoiceLines.InvoiceID

Secondo me questo è molto leggibile e semplice. Denominare le variabili come i e il è una scelta sbagliata in generale.

Ho appena iniziato a lavorare in un posto che utilizza solo " ID " (nelle tabelle principali, a cui fa riferimento TableNameID in chiavi esterne) e hanno già riscontrato DUE problemi di produzione direttamente causati da esso.

In un caso la query ha utilizzato " ... dove ID in (SELEZIONA ID DA Altra tabella ... " invece di " ... dove ID in (SELEZIONA TRANSID DA Altra tabella ... ".

Qualcuno può dire onestamente che non sarebbe stato molto più facile individuare se fossero stati usati nomi completi e coerenti in cui la frase errata avrebbe letto " ... dove TransID in (SELECT OtherTableID da OtherTable ... " ;? Non credo.

L'altro problema si verifica durante il refactoring del codice. Se utilizzi una tabella temporanea mentre in precedenza la query passava da una tabella principale, il vecchio codice legge " ... dbo.MyFunction (t.ID) ... " e se ciò non viene modificato ma "t" ora si riferisce a una tabella temporanea anziché alla tabella principale, non si ottiene nemmeno un errore - solo risultati errati.

Se la generazione di errori non necessari è un obiettivo (forse alcune persone non hanno abbastanza lavoro?), questo tipo di convenzione di denominazione è ottima. Altrimenti la denominazione coerente è la strada da percorrere.

Per semplicità, la maggior parte delle persone nomina la colonna sull'ID tabella. Se ha un riferimento di chiave esterna su un'altra tabella, allora lo chiamano esplicitamente InvoiceID (per usare il tuo esempio) nel caso di join, stai comunque aliasando la tabella in modo che l'identificativo inv.ID esplicito sia ancora più semplice di inv.InvoiceID

Venendo a questo dal punto di vista di un dizionario di dati formale, vorrei nominare l'elemento di dati invoice_ID . Generalmente, il nome di un elemento di dati sarà univoco nel dizionario dei dati e idealmente avrà lo stesso nome dappertutto, sebbene a volte possano essere richiesti termini qualificativi aggiuntivi in ??base al contesto, ad es. l'elemento di dati denominato employee_ID potrebbe essere utilizzato due volte nell'organigramma e pertanto qualificato rispettivamente come supervisor_employee_ID e subordinate_employee_ID .

Ovviamente, le convenzioni di denominazione sono soggettive e una questione di stile. Ho trovato le linee guida ISO / IEC 11179 per essere un utile punto di partenza.

Per il DBMS, vedo le tabelle come raccolte di entità (ad eccezione di quelle che contengono sempre e solo una riga, ad es. tabella di cofig, tabella delle costanti, ecc.) ad es. la tabella in cui il mio employee_ID è la chiave sarebbe denominata Personale . Quindi subito la convenzione TableNameID non funziona per me.

Ho visto lo stile TableName.ID = PK TableNameID = FK utilizzato su modelli di dati di grandi dimensioni e devo dire che lo trovo un po 'confuso: preferisco di gran lunga lo stesso nome di un identificatore, ad es. non cambia il nome in base alla tabella in cui appare. Qualcosa da notare è lo stile di cui sopra sembra essere usato nei negozi che aggiungono una colonna IDENTITY (auto-incremento) a ogni mentre si evitano le chiavi naturali e composte in chiavi esterne. Quei negozi tendono a non avere dizionari di dati formali né costruire da modelli di dati. Ancora una volta, questa è solo una questione di stile e una a cui non sottoscrivo personalmente. Quindi, alla fine, non fa per me.

Detto ciò, posso vedere un caso per cui talvolta il qualificatore viene eliminato dal nome della colonna quando il nome della tabella fornisce un contesto per farlo, ad es. l'elemento chiamato employee_last_name può diventare semplicemente last_name nella tabella Personale . La logica in questo caso è che il dominio è "cognome delle persone" ed è più probabile che sia UNION ed edito con last_name colonne da altre tabelle anziché essere usato come chiave esterna in un'altra tabella, ma poi di nuovo ... Potrei semplicemente cambiare idea, a volte non si può mai dire. Questa è la cosa: la modellazione dei dati è in parte arte, in parte scienza.

Io personalmente preferisco (come è stato detto sopra) il Table.ID per PK e TableID per FK . Anche (per favore non spararmi) Microsoft Access lo consiglia.

TUTTAVIA, ANCHE so per certo che alcuni strumenti di generazione favoriscono il TableID per PK perché tendono a collegare tutti i nomi di colonna che contengono 'ID' nella parola INCLUDING ID! !!

Anche il designer delle query lo fa su Microsoft SQL Server (e per ogni query che crei, finisci per strappare tutte le relazioni appena create non necessarie su tutte le tabelle sull'ID colonna)

QUANTO Per quanto il mio disturbo ossessivo compulsivo interno lo odia, io rotolo con la convenzione TableID . Ricordiamo che si chiama Data BASE , poiché sarà la base per sperare che molte, molte, molte altre applicazioni vengano. E tutte le tecnologie dovrebbero beneficiare di uno schema ben normalizzato con una chiara descrizione.

Inutile dire che faccio delineare la mia linea quando le persone iniziano a usare TableName, TableDescription e simili. Secondo me, le convenzioni dovrebbero fare quanto segue:

  • Nome tabella: pluralizzato. Ex. I dipendenti
  • Alias ??tabella: Nome tabella completa, singolarizzato. Es.

    SELECT Employee.*, eMail.Address
    FROM Employees AS Employee LEFT JOIN eMails as eMail on Employee.eMailID = eMail.eMailID -- I would sure like it to just have the eMail.ID here.... but oh well
    

[Aggiornamento]

Inoltre, in questa discussione ci sono alcuni post validi su colonne duplicate dovute al "tipo di relazione" o ruolo. Ad esempio, se un negozio ha un EmployeeID , questo mi dice che è occupata. Quindi a volte faccio qualcosa come Store.EmployeeID_Manager . Certo, è un po 'più grande, ma in alcuni casi la gente non impazzirà nel tentativo di trovare ID gestore tabella , o cosa sta facendo EmployeeID . Quando si esegue una query è DOVE lo semplificherei come:     SELEZIONA EmployeeID_Manager come ManagerID FROM Store

Penso che tu possa usare qualsiasi cosa per l'ID " " purché tu sia coerente. È importante includere il nome della tabella. Suggerirei di utilizzare uno strumento di modellazione come Erwin per applicare le convenzioni e gli standard di denominazione, quindi quando si scrivono query è facile comprendere le relazioni che possono esistere tra le tabelle.

Quello che intendo con la prima affermazione è, invece di ID puoi usare qualcos'altro come 'recno'. Quindi questa tabella avrebbe un PK di invoice_recno e così via.

Saluti, Ben

Il mio voto è per InvoiceID per l'ID tabella. Uso anche la stessa convenzione di denominazione quando viene utilizzata come chiave esterna e utilizzo di nomi di alias intelligenti nelle query.

 Select Invoice.InvoiceID, Lines.InvoiceLine, Customer.OrgName
 From Invoices Invoice
 Join InvoiceLines Lines on Lines.InvoiceID = Invoice.InvoiceID
 Join Customers Customer on Customer.CustomerID = Invoice.CustomerID

Certo, è più lungo di alcuni altri esempi. Ma sorridi. Questo è per i posteri e un giorno, un povero programmatore junior dovrà cambiare il tuo capolavoro. In questo esempio non c'è ambiguità e man mano che vengono aggiunte ulteriori tabelle alla query, sarai grato per la verbosità.

Per il nome della colonna nel database, usare " InvoiceID " ;.

Se copio i campi in una struttura senza nome tramite LINQ, posso denominarlo " ID " lì, se è l'unico ID nella struttura.

Se la colonna NON verrà utilizzata in una chiave esterna, in modo che venga utilizzata solo per identificare in modo univoco una riga per la modifica o l'eliminazione, la chiamerò " PK " ;.

Se dai a ogni chiave un nome univoco, ad es. & Quot; invoices.invoice_id " invece di " invoices.id " ;, quindi puoi utilizzare " natural join " e " utilizzando " operatori senza preoccupazioni. Per es.

SELECT * FROM invoices NATURAL JOIN invoice_lines
SELECT * FROM invoices JOIN invoice_lines USING (invoice_id)

anziché

SELECT * from invoices JOIN invoice_lines
    ON invoices.id = invoice_lines.invoice_id

SQL è abbastanza dettagliato senza renderlo più dettagliato.

Quello che faccio per mantenere le cose coerenti per me stesso (dove una tabella ha una chiave primaria a colonna singola usata come ID) è nominare la chiave primaria della tabella Table_pk . Ovunque io abbia una chiave esterna che punta a quella chiave primaria delle tabelle, chiamo la colonna PrimaryKeyTable_fk . In questo modo so che se ho un Customer_pk nella mia tabella Customer e un Customer_fk nella mia tabella Order, so che la tabella Order si riferisce a una voce nel Customer tavolo.

Per me questo ha senso soprattutto per i join in cui penso che leggano più facilmente.

SELECT * 
FROM Customer AS c
    INNER JOIN Order AS c ON c.Customer_pk = o.Customer_fk

FWIW, il nostro nuovo standard (che cambia, intendo "si evolve" con ogni nuovo progetto) è:

  • Nomi dei campi del database in minuscolo
  • Nomi delle tabelle maiuscole
  • Usa i caratteri di sottolineatura per separare le parole nel nome del campo - convertile in maiuscolo nel codice.
  • pk_ prefisso significa chiave primaria
  • Il suffisso
  • _id indica un ID intero, ID autoincremento
  • Il prefisso
  • fk_ significa chiave esterna (nessun suffisso necessario)
  • _VW suffisso per le visualizzazioni
  • is_ prefisso per i booleani

Quindi, una tabella denominata NAMES potrebbe avere i campi pk_name_id, first_name, last_name, is_alive, e fk_company e una vista chiamata LIVING_CUSTOMERS_VW , definito come:

SELECT first_name, last_name
FROM CONTACT.NAMES
WHERE (is_alive = 'True')

Come altri hanno detto, tuttavia, quasi ogni schema funzionerà finché sarà coerente e non offusca inutilmente i tuoi significati.

Sono assolutamente d'accordo con l'inclusione del nome della tabella nel nome del campo ID, esattamente per le ragioni fornite. In genere, questo è l'unico campo in cui includerei il nome della tabella.

Odio il semplice nome ID. Preferisco fortemente utilizzare sempre invoice_id o una sua variante. So sempre quale tabella è la tabella autorevole per l'id quando devo, ma questo mi confonde

SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.InvoiceID = inv.ID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.ID = inv.InvoiceLineID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.ID = inv.InvoiceID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.InvoiceLineID = inv.ID 

La cosa peggiore di tutte è il mix che menzioni, totalmente confuso. Ho dovuto lavorare con un database dove quasi sempre era foo_id tranne in uno degli ID più usati. È stato un vero inferno.

Preferisco DomainName || 'ID'. (ovvero DomainName + ID)

DomainName è spesso, ma non sempre, uguale a TableName.

Il problema con ID da solo è che non si ingrandisce. Una volta che hai circa 200 tabelle, ognuna con una prima colonna denominata ID, i dati iniziano a sembrare tutti uguali. Se qualifichi sempre l'ID con il nome della tabella, questo aiuta un po ', ma non molto.

DomainName & amp; L'ID può essere utilizzato per nominare chiavi esterne e chiavi primarie. Quando le chiavi foriegn prendono il nome dalla colonna a cui fanno riferimento, ciò può essere di aiuto mnemonico. Formalmente, non è necessario legare il nome di una chiave esterna alla chiave a cui fa riferimento, poiché il vincolo di integrità referenziale stabilirà il riferimento. Ma è estremamente utile quando si tratta di leggere query e aggiornamenti.

Occasionalmente, DomainName || 'ID' non può essere usato, perché ci sarebbero due colonne nella stessa tabella con lo stesso nome. Esempio: Employees.EmployeeID e Employees.SupervisorID. In questi casi, utilizzo RoleName || "ID", come nell'esempio.

Ultimo ma non meno importante, quando possibile uso le chiavi naturali anziché quelle sintetiche. Ci sono situazioni in cui le chiavi naturali non sono disponibili o non affidabili, ma ci sono molte situazioni in cui la chiave naturale è la scelta giusta. In quei casi, lascio che la chiave naturale prenda il nome che avrebbe naturalmente. Questo nome spesso non contiene nemmeno le lettere, "ID". Esempio: OrderNo dove No è ??un'abbreviazione per " Number " ;.

Per ogni tabella scelgo una scorciatoia con lettera ad albero (ad es. Employees = > Emp)

In questo modo una chiave primaria numerica automatica diventa nkEmp .

È breve, unico nell'intero database e conosco esattamente le sue proprietà a colpo d'occhio.

Conservo gli stessi nomi in SQL e in tutte le lingue che utilizzo (principalmente C #, Javascript, VB6).

Vedi convenzioni di denominazione per un sistema ben studiato di tabelle e colonne di denominazione. Il metodo utilizza un suffisso per ogni tabella ( _prd per una tabella del prodotto o _ctg per una tabella delle categorie) e lo aggiunge a ciascuna colonna di una determinata tabella. Quindi la colonna identità per la tabella dei prodotti sarebbe id_prd ed è quindi unica nel database.

Fanno un ulteriore passo per aiutare a comprendere le chiavi esterne: la chiave esterna nella tabella del prodotto che fa riferimento alla tabella delle categorie sarebbe idctg_prd in modo che sia ovvio a quale tabella appartiene ( _prd e a quale tabella fa riferimento (categoria).

I vantaggi sono che non vi è alcuna ambiguità con le colonne di identità in diverse tabelle e che si può dire a colpo d'occhio a quali colonne fa riferimento una query con i nomi delle colonne.

È possibile utilizzare la seguente convenzione di denominazione. Ha i suoi difetti ma risolve i tuoi problemi particolari.

  1. Usa nickname brevi (3-4 caratteri) per i nomi delle tabelle, ovvero Fattura - inv , InvoiceLines - invl
  2. Assegna un nome alle colonne nella tabella usando quei soprannomi, ovvero inv_id , invl_id
  3. Per le colonne di riferimento usa invl_inv_id per i nomi.

in questo modo potresti dire

SELECT * FROM Invoice LEFT JOIN InvoiceLines ON inv_id = invl_inv_id
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top