ORA-00907:fehlende rechte Klammer
Dies ist eine von mehreren allgemeinen Fehlermeldungen, die darauf hinweisen, dass unser Code einen oder mehrere Syntaxfehler enthält. Manchmal kann es bedeuten, dass wir buchstäblich eine rechte Klammer weggelassen haben; das ist einfach zu überprüfen, ob wir einen Editor verwenden, der eine Match-Klammer hat Fähigkeit (die meisten Texteditoren, die sich an Programmierer richten, tun dies). Aber oft bedeutet dies, dass der Compiler auf ein Schlüsselwort gestoßen ist, das aus dem Zusammenhang gerissen wurde. Oder vielleicht ist es ein falsch geschriebenes Wort, ein Leerzeichen anstelle eines Unterstrichs oder ein fehlendes Komma.
Leider sind die möglichen Gründe, warum unser Code nicht kompiliert, praktisch unendlich und der Compiler ist einfach nicht schlau genug, um sie zu unterscheiden. Also schleudert es eine generische, leicht kryptische Nachricht wie ORA-00907: missing right parenthesis
und überlässt es uns, den eigentlichen Bloomer zu erkennen.
Das gepostete Skript hat mehrere Syntaxfehler. Zuerst werde ich den Fehler besprechen, der ORA-0097 auslöst, aber Sie müssen sie alle beheben.
Fremdschlüsseleinschränkungen können in Übereinstimmung mit der referenzierenden Spalte oder auf Tabellenebene deklariert werden, nachdem alle Spalten deklariert wurden. Diese haben unterschiedliche Syntaxen; Ihre Skripte mischen die beiden und deshalb erhalten Sie ORA-00907.
Die Inline-Deklaration hat kein Komma und enthält nicht den referenzierenden Spaltennamen.
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)
Einschränkungen auf Tabellenebene sind eine separate Komponente und müssen daher mit einem Komma versehen sein und die referenzierende Spalte erwähnen.
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)
Hier ist eine Liste anderer Syntaxfehler:
- Die referenzierte Tabelle (und der referenzierte Primärschlüssel oder Unique Constraint) müssen bereits existieren, bevor wir einen Fremdschlüssel für sie erstellen können. Sie können also keinen Fremdschlüssel für
HISTORYS_T
erstellen bevor Sie die referenziertenORDERS
erstellt haben Tabelle. - Sie haben die Namen der referenzierten Tabellen in einigen der Fremdschlüsselklauseln falsch geschrieben (
LIBRARY_T
undFORMAT_T
). - Sie müssen einen Ausdruck in der DEFAULT-Klausel angeben. Für DATE-Spalten ist dies normalerweise das aktuelle Datum,
DATE DEFAULT sysdate
.
Unseren eigenen Code mit kühlem Auge zu betrachten, ist eine Fähigkeit, die wir uns alle aneignen müssen, um als Entwickler erfolgreich zu sein. Es ist wirklich hilfreich, sich mit der Dokumentation von Oracle vertraut zu machen. Ein direkter Vergleich Ihres Codes und der Beispiele in der SQL-Referenz hätte Ihnen geholfen, diese Syntaxfehler in deutlich weniger als zwei Tagen zu beheben. Finden Sie es hier (11g) und hier (12c).
Ihre Skripte enthalten nicht nur Syntaxfehler, sondern auch Designfehler. Dies sind keine Fehler, sondern schlechte Praktiken, die nicht zur Gewohnheit werden sollten.
- Sie haben die meisten Ihrer Einschränkungen nicht genannt. Oracle wird ihnen einen Standardnamen geben, aber es wird ein schrecklicher sein und das Datenwörterbuch schwerer verständlich machen. Die explizite Benennung jeder Einschränkung hilft uns, durch die physische Datenbank zu navigieren. Es führt auch zu verständlicheren Fehlermeldungen, wenn unsere SQL eine Einschränkungsverletzung auslöst.
- Benennen Sie Ihre Einschränkungen konsistent.
HISTORY_T
hat Beschränkungen namenshistorys_T_FK
undfk_order_id_orders
, beides ist nicht hilfreich. Eine nützliche Konvention ist<child_table>_<parent_table>_fk
. Alsohistory_customer_fk
undhistory_order_fk
bzw.. - Es kann sinnvoll sein, die Einschränkungen mit separaten Anweisungen zu erstellen. Durch das Erstellen von Tabellen, dann von Primärschlüsseln und dann von Fremdschlüsseln werden die oben identifizierten Probleme mit der Reihenfolge der Abhängigkeiten vermieden.
- Sie versuchen, zyklische Fremdschlüssel zu erstellen zwischen
LIBRARY_T
undFORMATS
. Sie könnten dies tun, indem Sie die Einschränkungen in einer separaten Anweisung erstellen, tun Sie dies jedoch nicht:Sie werden Probleme beim Einfügen von Zeilen und noch schlimmere Probleme beim Löschen haben. Sie sollten Ihr Datenmodell überdenken und einen Weg finden, die Beziehung zwischen den beiden Tabellen so zu modellieren, dass eine die übergeordnete und die andere die untergeordnete Tabelle ist. Oder vielleicht benötigen Sie eine andere Art von Beziehung, z. B. eine Schnittpunkttabelle. - Vermeiden Sie Leerzeilen in Ihren Skripten. Einige Tools werden damit umgehen, andere nicht. Wir können SQL*Plus so konfigurieren, dass sie damit umgehen, aber es ist besser, die Notwendigkeit zu vermeiden.
- Die Namenskonvention von
LIBRARY_T
ist hässlich. Versuchen Sie, einen aussagekräftigeren Namen zu finden, der kein unnötiges Suffix erfordert, um einen Keyword-Konflikt zu vermeiden. T_CUSTOMERS
ist sogar noch hässlicher, da es sowohl inkonsistent mit Ihren anderen Tabellen als auch völlig unnötig ist, alscustomers
ist kein Schlüsselwort.
Dinge zu benennen ist schwierig. Sie würden nicht glauben, was ich im Laufe der Jahre über Tischnamen geführt habe. Das Wichtigste ist die Konsistenz. Wenn ich mir ein Datenwörterbuch ansehe und Tabellen mit dem Namen T_CUSTOMERS
sehe und LIBRARY_T
Meine erste Antwort wäre Verwirrung. Warum werden diese Tabellen mit unterschiedlichen Konventionen benannt? Welcher konzeptionelle Unterschied drückt sich das aus? Entscheiden Sie sich also bitte für eine Namenskonvention und halten Sie sich daran. Machen Sie Ihre Tabellennamen entweder alle Singular oder alle Plural. Vermeiden Sie Präfixe und Suffixe so weit wie möglich; Wir wissen bereits, dass es sich um eine Tabelle handelt, wir brauchen kein T_
oder ein _TAB
.