ORA-00907:parentesi a destra mancante
Questo è uno dei numerosi messaggi di errore generici che indicano che il nostro codice contiene uno o più errori di sintassi. A volte può significare che abbiamo letteralmente omesso una parentesi quadra; è abbastanza facile verificare se stiamo usando un editor che ha una parentesi di corrispondenza capacità (la maggior parte degli editor di testo rivolti ai programmatori lo fanno). Ma spesso significa che il compilatore si è imbattuto in una parola chiave fuori contesto. O forse è una parola errata, uno spazio invece di un trattino basso o una virgola mancante.
Sfortunatamente le possibili ragioni per cui il nostro codice non verrà compilato sono virtualmente infinite e il compilatore non è abbastanza intelligente per distinguerle. Quindi lancia un messaggio generico, leggermente criptico, come ORA-00907: missing right parenthesis
e lascia a noi il compito di individuare il vero fiore all'occhiello.
Lo script pubblicato presenta diversi errori di sintassi. Per prima cosa discuterò l'errore che attiva quell'ORA-0097 ma dovrai risolverli tutti.
I vincoli di chiave esterna possono essere dichiarati in linea con la colonna di riferimento oa livello di tabella dopo che tutte le colonne sono state dichiarate. Questi hanno sintassi diverse; i tuoi script mescolano i due ed è per questo che ottieni ORA-00907.
La dichiarazione in linea non contiene una virgola e non include il nome della colonna di riferimento.
CREATE TABLE historys_T (
history_record VARCHAR2 (8),
customer_id VARCHAR2 (8)
CONSTRAINT historys_T_FK FOREIGN KEY REFERENCES T_customers ON DELETE CASCADE,
order_id VARCHAR2 (10) NOT NULL,
CONSTRAINT fk_order_id_orders REFERENCES orders ON DELETE CASCADE)
I vincoli a livello di tabella sono un componente separato, quindi hanno una virgola e menzionano la colonna di riferimento.
CREATE TABLE historys_T (
history_record VARCHAR2 (8),
customer_id VARCHAR2 (8),
order_id VARCHAR2 (10) NOT NULL,
CONSTRAINT historys_T_FK FOREIGN KEY (customer_id) REFERENCES T_customers ON DELETE CASCADE,
CONSTRAINT fk_order_id_orders FOREIGN KEY (order_id) REFERENCES orders ON DELETE CASCADE)
Ecco un elenco di altri errori di sintassi:
- La tabella referenziata (e la chiave primaria referenziata o il vincolo univoco) devono già esistere prima di poter creare una chiave esterna contro di esse. Quindi non puoi creare una chiave esterna per
HISTORYS_T
prima di aver creato gliORDERS
di riferimento tabella. - Hai sbagliato a scrivere i nomi delle tabelle referenziate in alcune clausole di chiave esterna (
LIBRARY_T
eFORMAT_T
). - È necessario fornire un'espressione nella clausola DEFAULT. Per le colonne DATE che di solito è la data corrente,
DATE DEFAULT sysdate
.
Guardare il nostro codice con occhio freddo è un'abilità che tutti dobbiamo acquisire per avere successo come sviluppatori. È davvero utile avere familiarità con la documentazione di Oracle. Un confronto fianco a fianco del tuo codice e degli esempi in SQL Reference ti avrebbe aiutato a risolvere questi errori di sintassi in molto meno di due giorni. Lo trovi qui (11g) e qui (12c).
Oltre agli errori di sintassi, i tuoi script contengono errori di progettazione. Questi non sono fallimenti, ma cattive pratiche che non dovrebbero diventare abitudini.
- Non hai nominato la maggior parte dei tuoi vincoli. Oracle darà loro un nome predefinito ma sarà orribile e renderà più difficile la comprensione del dizionario dei dati. Denominare in modo esplicito ogni vincolo ci aiuta a navigare nel database fisico. Porta anche a messaggi di errore più comprensibili quando il nostro SQL fa scattare una violazione del vincolo.
- Assegna un nome coerente ai tuoi vincoli.
HISTORY_T
ha vincoli chiamatihistorys_T_FK
efk_order_id_orders
, nessuno dei quali è utile. Una convenzione utile è<child_table>_<parent_table>_fk
. Quindihistory_customer_fk
ehistory_order_fk
rispettivamente. - Può essere utile creare i vincoli con istruzioni separate. La creazione di tabelle, quindi chiavi primarie e poi chiavi esterne, eviterà i problemi con l'ordinamento delle dipendenze identificati sopra.
- Stai cercando di creare chiavi esterne cicliche tra
LIBRARY_T
eFORMATS
. Potresti farlo creando i vincoli in un'istruzione separata ma non farlo:avrai problemi durante l'inserimento di righe e problemi ancora peggiori con le eliminazioni. Dovresti riconsiderare il tuo modello di dati e trovare un modo per modellare la relazione tra le due tabelle in modo che uno sia il genitore e l'altro il figlio. O forse hai bisogno di un diverso tipo di relazione, come una tabella di intersezione. - Evita le righe vuote nei tuoi script. Alcuni strumenti li gestiranno ma altri no. Possiamo configurare SQL*Plus per gestirli ma è meglio evitare la necessità.
- La convenzione di denominazione di
LIBRARY_T
è brutto. Prova a trovare un nome più espressivo che non richieda un suffisso inutile per evitare un conflitto di parole chiave. T_CUSTOMERS
è ancora più brutto, essendo sia incoerente con le altre tabelle che completamente non necessario, comecustomers
non è una parola chiave.
Dare un nome alle cose è difficile. Non crederesti alle discussioni che ho avuto sui nomi dei tavoli nel corso degli anni. La cosa più importante è la coerenza. Se guardo un dizionario di dati e vedo tabelle chiamate T_CUSTOMERS
e LIBRARY_T
la mia prima risposta sarebbe confusione. Perché queste tabelle sono denominate con convenzioni diverse? Quale differenza concettuale questo esprime? Quindi, per favore, decidi una convenzione di denominazione e attieniti. Rendi i nomi delle tue tabelle tutti singolari o tutti plurali. Evita il più possibile prefissi e suffissi; sappiamo già che è una tabella, non abbiamo bisogno di un T_
o un _TAB
.