ORA-00907:brak prawego nawiasu
Jest to jeden z kilku ogólnych komunikatów o błędach, które wskazują, że nasz kod zawiera jeden lub więcej błędów składniowych. Czasami może to oznaczać, że dosłownie pominęliśmy prawy nawias; to dość łatwe do sprawdzenia, czy używamy edytora, który ma nawias dopasowania możliwości (większość edytorów tekstu skierowanych do programistów). Ale często oznacza to, że kompilator natrafił na słowo kluczowe wyrwane z kontekstu. A może jest to błędnie napisane słowo, spacja zamiast podkreślenia lub brakujący przecinek.
Niestety możliwe powody, dla których nasz kod się nie skompiluje, są praktycznie nieskończone, a kompilator po prostu nie jest na tyle sprytny, aby je rozróżnić. Zawiera więc ogólną, nieco zagadkową wiadomość, taką jak ORA-00907: missing right parenthesis
i zostawia nam to, abyśmy zauważyli rzeczywiste gafa.
Opublikowany skrypt zawiera kilka błędów składniowych. Najpierw omówię błąd, który uruchamia ORA-0097, ale musisz je wszystkie naprawić.
Ograniczenia klucza obcego można zadeklarować zgodnie z kolumną odniesienia lub na poziomie tabeli po zadeklarowaniu wszystkich kolumn. Mają one różną składnię; twoje skrypty mieszają te dwa i dlatego otrzymujesz ORA-00907.
Deklaracja w wierszu nie zawiera przecinka i nie zawiera nazwy kolumny odniesienia.
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)
Ograniczenia na poziomie tabeli są oddzielnym komponentem, dlatego mają przecinek i wspominają o kolumnie odniesienia.
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)
Oto lista innych błędów składniowych:
- Tabela, do której się odwołuje (i klucz podstawowy lub ograniczenie unikatowe), musi już istnieć, zanim będziemy mogli utworzyć dla nich klucz obcy. Więc nie możesz utworzyć klucza obcego dla
HISTORYS_T
zanim utworzyłeś przywoływaneORDERS
stół. - Błędnie napisałeś nazwy tabel, do których się odwołujesz w niektórych klauzulach kluczy obcych (
LIBRARY_T
iFORMAT_T
). - Musisz podać wyrażenie w klauzuli DEFAULT. W przypadku kolumn DATE, które zwykle są bieżącą datą,
DATE DEFAULT sysdate
.
Spojrzenie na własny kod chłodnym okiem to umiejętność, którą wszyscy musimy zdobyć, aby odnieść sukces jako programiści. Naprawdę pomaga zapoznać się z dokumentacją Oracle. Bezpośrednie porównanie twojego kodu i przykładów w SQL Reference pomogłoby ci rozwiązać te błędy składni w znacznie mniej niż dwa dni. Znajdziesz go tutaj (11g) i tutaj (12c).
Oprócz błędów składniowych, twoje skrypty zawierają błędy projektowe. To nie są porażki, ale złe praktyki, które nie powinny stać się nawykami.
- Nie wymieniłeś większości swoich ograniczeń. Oracle nada im domyślną nazwę, ale będzie to okropna i sprawi, że słownik danych będzie trudniejszy do zrozumienia. Jawne nazwanie każdego ograniczenia pomaga nam poruszać się po fizycznej bazie danych. Prowadzi to również do bardziej zrozumiałych komunikatów o błędach, gdy nasz SQL sygnalizuje naruszenie ograniczenia.
- Spójnie nazwij swoje ograniczenia.
HISTORY_T
ma ograniczenia o nazwiehistorys_T_FK
ifk_order_id_orders
, z których żadna nie jest pomocna. Przydatną konwencją jest<child_table>_<parent_table>_fk
. Więchistory_customer_fk
ihistory_order_fk
odpowiednio. - Przydatne może być tworzenie ograniczeń za pomocą oddzielnych instrukcji. Tworzenie tabel, następnie kluczy podstawowych, a następnie kluczy obcych pozwoli uniknąć problemów z kolejnością zależności zidentyfikowanych powyżej.
- Próbujesz utworzyć cykliczne klucze obce między
LIBRARY_T
iFORMATS
. Możesz to zrobić, tworząc ograniczenia w oddzielnych instrukcjach, ale nie rób tego:będziesz miał problemy z wstawianiem wierszy, a jeszcze gorsze problemy z usuwaniem. Należy ponownie rozważyć model danych i znaleźć sposób na modelowanie relacji między dwiema tabelami, tak aby jedna była nadrzędną, a druga podrzędną. A może potrzebujesz innego rodzaju relacji, na przykład tabeli przecięcia. - Unikaj pustych wierszy w skryptach. Niektóre narzędzia sobie z nimi poradzą, ale niektóre nie. Możemy skonfigurować SQL*Plus, aby je obsłużyć, ale lepiej jest uniknąć takiej potrzeby.
- Konwencja nazewnictwa
LIBRARY_T
jest brzydki. Spróbuj znaleźć bardziej wyrazistą nazwę, która nie wymaga niepotrzebnego przyrostka, aby uniknąć kolizji słów kluczowych. T_CUSTOMERS
jest jeszcze brzydszy, będąc zarówno niespójny z innymi tabelami, jak i całkowicie niepotrzebny, jakocustomers
nie jest słowem kluczowym.
Nazywanie rzeczy jest trudne. Nie uwierzyłbyś w te kłótnie, które przez lata toczyłem o nazwy stołów. Najważniejsza jest spójność. Jeśli spojrzę na słownik danych i zobaczę tabele o nazwie T_CUSTOMERS
i LIBRARY_T
moją pierwszą odpowiedzią byłoby zamieszanie. Dlaczego nazwy tych tabel mają różne konwencje? Jaka różnica pojęciowa czy to wyraża? Dlatego proszę, zdecyduj się na konwencję nazewnictwa i trzymaj się jej. Nadaj nazwy tabel albo w liczbie pojedynczej, albo w liczbie mnogiej. Unikaj prefiksów i sufiksów tak bardzo, jak to możliwe; wiemy już, że to stół, nie potrzebujemy T_
lub _TAB
.