ORA-00907:manglende højre parentes
Dette er en af flere generiske fejlmeddelelser, som angiver, at vores kode indeholder en eller flere syntaksfejl. Nogle gange kan det betyde, at vi bogstaveligt talt har udeladt en højre parentes; det er nemt nok at bekræfte, om vi bruger en editor, der har en match-parentes kapacitet (det gør de fleste teksteditorer rettet mod kodere). Men ofte betyder det, at compileren er stødt på et søgeord uden for kontekst. Eller måske er det et forkert stavet ord, et mellemrum i stedet for en understregning eller et manglende komma.
Desværre er de mulige årsager til, at vores kode ikke vil kompilere, praktisk talt uendelige, og compileren er bare ikke klog nok til at skelne dem. Så den sender en generisk, lidt kryptisk besked som ORA-00907: missing right parenthesis
og overlader det til os at få øje på selve blomstringen.
Det udsendte script har flere syntaksfejl. Først vil jeg diskutere fejlen, der udløser den ORA-0097, men du bliver nødt til at rette dem alle.
Fremmednøglebegrænsninger kan erklæres på linje med referencekolonnen eller på tabelniveau, efter at alle kolonnerne er blevet erklæret. Disse har forskellige syntakser; dine scripts blander de to, og det er derfor, du får ORA-00907.
Indbygget erklæring har ikke et komma og inkluderer ikke referencekolonnens navn.
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)
Tabelniveaubegrænsninger er en separat komponent, og de har også et komma og nævner den refererende kolonne.
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)
Her er en liste over andre syntaksfejl:
- Den refererede tabel (og den refererede primærnøgle eller unikke begrænsning) skal allerede eksistere, før vi kan oprette en fremmednøgle mod dem. Så du kan ikke oprette en fremmednøgle til
HISTORYS_T
før du har oprettet den refereredeORDERS
tabel. - Du har stavet navnene på de refererede tabeller forkert i nogle af de fremmede nøgleudtryk (
LIBRARY_T
ogFORMAT_T
). - Du skal angive et udtryk i DEFAULT-udtrykket. For DATE-kolonner, der normalt er den aktuelle dato,
DATE DEFAULT sysdate
.
At se på vores egen kode med et koldt øje er en færdighed, vi alle skal opnå for at få succes som udviklere. Det hjælper virkelig at være bekendt med Oracles dokumentation. En side-by-side sammenligning af din kode og eksemplerne i SQL Reference ville have hjulpet dig med at løse disse syntaksfejl på betydeligt mindre end to dage. Find det her (11g) og her (12c).
Ud over syntaksfejl indeholder dine scripts designfejl. Det er ikke fejl, men dårlig praksis, som ikke bør blive til vaner.
- Du har ikke navngivet de fleste af dine begrænsninger. Oracle vil give dem et standardnavn, men det vil være et forfærdeligt navn og gør dataordbogen sværere at forstå. Eksplicit navngivning af hver begrænsning hjælper os med at navigere i den fysiske database. Det fører også til mere forståelige fejlmeddelelser, når vores SQL udløser en begrænsningsovertrædelse.
- Navngiv dine begrænsninger konsekvent.
HISTORY_T
har begrænsninger kaldethistorys_T_FK
ogfk_order_id_orders
, hvoraf ingen af dem er nyttige. En nyttig konvention er<child_table>_<parent_table>_fk
. Såhistory_customer_fk
oghistory_order_fk
hhv. - Det kan være nyttigt at oprette begrænsningerne med separate udsagn. Oprettelse af tabeller og derefter primære nøgler og derefter fremmednøgler vil undgå problemerne med afhængighedsrækkefølge identificeret ovenfor.
- Du forsøger at oprette cykliske fremmednøgler mellem
LIBRARY_T
ogFORMATS
. Du kan gøre dette ved at oprette begrænsningerne i en separat erklæring, men gør det ikke:du vil få problemer med at indsætte rækker og endnu værre problemer med sletninger. Du bør genoverveje din datamodel og finde en måde at modellere forholdet mellem de to tabeller på, så den ene er forælderen og den anden barnet. Eller måske har du brug for en anden form for relation, såsom en skæringstabel. - Undgå tomme linjer i dine scripts. Nogle værktøjer vil håndtere dem, men nogle vil ikke. Vi kan konfigurere SQL*Plus til at håndtere dem, men det er bedre at undgå behovet.
- Navnekonventionen for
LIBRARY_T
er grim. Prøv at finde et mere udtryksfuldt navn, som ikke kræver et unødvendigt suffiks for at undgå et søgeordssammenstød. T_CUSTOMERS
er endnu grimmere, idet den både er inkonsistent med dine andre tabeller og fuldstændig unødvendig somcustomers
er ikke et søgeord.
At navngive ting er svært. Du ville ikke tro de skænderier, jeg har haft om bordnavne gennem årene. Det vigtigste er konsistens. Hvis jeg ser på en dataordbog og ser tabeller kaldet T_CUSTOMERS
og LIBRARY_T
mit første svar ville være forvirring. Hvorfor er disse tabeller navngivet med forskellige konventioner? Hvilken konceptuel forskel udtrykker dette? Så vær venlig, beslut dig for en navnekonvention og hold dig til. Gør dine tabelnavne enten alle ental eller alle flertal. Undgå så vidt muligt præfikser og suffikser; vi ved allerede, at det er en tabel, vi behøver ikke en T_
eller en _TAB
.