Terminologia di MySQL & # 8220; vincoli & # 8221; vs & # 8220; chiavi esterne & # 8221; differenza?

StackOverflow https://stackoverflow.com/questions/310561

Domanda

Sto guardando i documenti MySQL qui e cercando di chiarire la distinzione tra CHIAVI STRANIERE e VINCOLI. Pensavo che un FK fosse un vincolo, ma i documenti sembrano parlarne come se fossero cose separate.

La sintassi per la creazione di un FK è (in parte) ...

[CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (index_col_name, ...)
    REFERENCES tbl_name (index_col_name,...)

Quindi il "VINCITORE" la clausola è facoltativa. Perché dovresti includerlo o non includerlo? Se lo lasci fuori, MySQL crea una chiave esterna ma non un vincolo? O è più simile a un "VINCITORE" non è altro che un nome per il tuo FK, quindi se non lo specifichi ottieni un FK anonimo?

Qualsiasi chiarimento sarebbe molto apprezzato.

Grazie,

Ethan

È stato utile?

Soluzione

Sì, una chiave esterna è un tipo di vincolo. MySQL ha un supporto irregolare per i vincoli:

  • PRIMARY KEY : sì come vincolo di tabella e vincolo di colonna.
  • FOREIGN KEY : sì come vincolo di tabella, ma solo con motori di archiviazione InnoDB e BDB; altrimenti analizzato ma ignorato.
  • CHECK : analizzato ma ignorato in tutti i motori di archiviazione.
  • UNIQUE : sì come vincolo di tabella e vincolo di colonna.
  • NOT NULL : sì come vincolo di colonna.
  • DEFERRABLE e altri attributi di vincolo: nessun supporto.

La clausola CONSTRAINT consente di assegnare un nome esplicito al vincolo, sia per rendere più leggibili i metadati sia per utilizzare il nome quando si desidera eliminare il vincolo. Lo standard SQL richiede che la clausola CONSTRAINT sia facoltativa. Se lo lasci fuori, RDBMS crea automaticamente un nome e il nome dipende dall'implementazione.

Altri suggerimenti

In generale (non necessario MySQL), le chiavi esterne sono vincoli, ma i vincoli non sono sempre chiavi esterne. Pensa a vincoli chiave primari, vincoli univoci ecc.

Tornando alla domanda specifica, hai ragione, omettendo la parte CONSTRAINT [simbolo] creerai un FK con un nome generato automaticamente.

Finora, i nostri DDL CREATE TABLE sono di questo formato: nota la sintassi UNIQUE KEY e FOREIGN KEY che abbiamo usato.

CREATE TABLE my_dbschema.my_table (
    id INT unsigned auto_increment PRIMARY KEY,
    account_nbr INT NOT NULL,
    account_name VARCHAR(50) NOT NULL,
    active_flg CHAR(1) NOT NULL DEFAULT 'Y',
    vendor_nbr INT NOT NULL,
    create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp,
    create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,
    last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    UNIQUE KEY uk1_my_table(account_nbr, account_name),
    FOREIGN KEY fk1_my_table(vendor_nbr) REFERENCES vendor(vendor_nbr)
    );

In questo formato, MySQL sta creando automaticamente INDEX-es con i nomi uk1_my_table e fk1_my_table; ma il nome dell'oggetto FK è diverso - my_table_ibfk_1 (cioè tablename_ibfk_N & # 8211; definito dal sistema). Quindi ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table non ha funzionato (e quindi frustrante e suscitando allarmi), dato che non c'è nessun oggetto FK db con quel nome.

Qui & # 8217; s un formato DDL alternativo scrive i costarints (Ref: https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html ): -

CREATE TABLE my_dbschema.my_table (
    id INT unsigned auto_increment PRIMARY KEY,
    account_nbr INT NOT NULL,
    account_name VARCHAR(50) NOT NULL,
    active_flg CHAR(1) NOT NULL DEFAULT 'Y',
    vendor_nbr INT NOT NULL,
    create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp,
    create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,
    last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    CONSTRAINT uk1_my_table UNIQUE KEY (account_nbr, account_name),
    CONSTRAINT fk1_my_table FOREIGN KEY (vendor_nbr) REFERENCES vendor(vendor_nbr)
    );

In questo formato, MySQL sta ancora creando INDEX-es con i nomi uk1_my_table e fk1_my_table automaticamente, ma il nome dell'oggetto FK non è qualcosa di diverso & # 8211; è fk1_my_table come menzionato nel DDL. Quindi ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table funziona, ma lascia dietro l'omonimo INDICE.

E nota che ALTER TABLE my_table DROP INDEX fk1_my_table non ha vinto inizialmente (quando l'FK non è ancora stato eliminato), con un messaggio di errore che viene utilizzato in un FK! Se il comando DROP FK è stato eseguito correttamente, solo allora DROP INDEX funziona.

Spero che questo spieghi e aiuti a risolvere la confusione.

Non posso rispondere per MySQL ma gli FK sono vincoli. Tutto ciò che forza i tuoi dati in una determinata condizione è un vincolo. Esistono diversi tipi di vincoli, Unico, Chiave primaria, Controllo e Chiavi esterne sono tutti vincoli. Forse MySQL ne ha altri.

A volte le parole sono consentite nei comandi ma non sono richieste per la leggibilità come il FROM nell'istruzione DELETE.

Se non sbaglio, i vincoli necessitano di indici, quindi quando si crea, ad esempio, un vincolo di chiave esterna, MySQL crea automaticamente anche un indice.

Questo è probabilmente il top più confuso in MySQL.

Molte persone affermano che, ad esempio, il "PRIMARY KEY", il "FOREIGN KEY" e il "UNIQUE" sono in realtà indici! (La documentazione ufficiale di MySQL è inclusa qui)

Molti altri, d'altra parte, affermano che sono piuttosto dei vincoli (il che ha senso, perché quando li usi, stai davvero imponendo restrizioni sulle colonne interessate).

Se sono davvero indici, qual è il punto nell'uso del clausola di vincolo per dargli un nome, dal momento che dovresti essere in grado di usare il nome di quell'indice quando lo hai creato?

Esempio:

... TASTO ESTERO nome_indice (col_name1, col_name2, ...)

Se FOREIGN KEY è un indice, dovremmo essere in grado di utilizzare index_name per gestirlo. Tuttavia, non possiamo.

Ma se non sono indici ma vere e proprie contraddizioni che usano gli indici per funzionare, allora ha senso.

In ogni caso, non lo sappiamo. In realtà, nessuno sembra saperlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top