ORA-00907:tanda kurung kanan tidak ada
Ini adalah salah satu dari beberapa pesan kesalahan umum yang menunjukkan kode kami berisi satu atau lebih kesalahan sintaks. Terkadang itu bisa berarti kita benar-benar telah menghilangkan tanda kurung siku; itu cukup mudah untuk memverifikasi jika kita menggunakan editor yang memiliki tanda kurung yang cocok kemampuan (sebagian besar editor teks yang ditujukan untuk pembuat kode melakukannya). Tetapi seringkali itu berarti kompiler menemukan kata kunci di luar konteks. Atau mungkin itu kata yang salah eja, spasi, bukan garis bawah atau koma yang hilang.
Sayangnya kemungkinan alasan mengapa kode kita tidak dapat dikompilasi hampir tidak terbatas dan kompilernya tidak cukup pintar untuk membedakannya. Jadi itu melemparkan pesan generik, sedikit samar, seperti ORA-00907: missing right parenthesis
dan menyerahkannya kepada kami untuk melihat kesalahan besar yang sebenarnya.
Skrip yang diposting memiliki beberapa kesalahan sintaksis. Pertama saya akan membahas kesalahan yang memicu ORA-0097 tetapi Anda harus memperbaiki semuanya.
Batasan kunci asing dapat dideklarasikan sesuai dengan kolom referensi atau pada tingkat tabel setelah semua kolom dideklarasikan. Ini memiliki sintaks yang berbeda; skrip Anda menggabungkan keduanya dan itulah mengapa Anda mendapatkan ORA-00907.
Deklarasi sebaris tidak memiliki koma dan tidak menyertakan nama kolom referensi.
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)
Batasan tingkat tabel adalah komponen yang terpisah, jadi gunakan koma dan sebutkan kolom referensi.
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)
Berikut adalah daftar kesalahan sintaks lainnya:
- Tabel yang direferensikan (dan kunci utama yang direferensikan atau batasan unik) harus sudah ada sebelum kita dapat membuat kunci asing untuk melawannya. Jadi Anda tidak dapat membuat kunci asing untuk
HISTORYS_T
sebelum Anda membuatORDERS
yang dirujuk meja. - Anda salah mengeja nama tabel yang direferensikan di beberapa klausa kunci asing (
LIBRARY_T
danFORMAT_T
). - Anda perlu memberikan ekspresi dalam klausa DEFAULT. Untuk kolom DATE yang biasanya tanggal sekarang,
DATE DEFAULT sysdate
.
Melihat kode kita sendiri dengan mata dingin adalah keterampilan yang kita semua butuhkan untuk menjadi sukses sebagai pengembang. Sangat membantu untuk terbiasa dengan dokumentasi Oracle. Perbandingan berdampingan kode Anda dan contoh dalam Referensi SQL akan membantu Anda mengatasi kesalahan sintaks ini dalam waktu kurang dari dua hari. Temukan di sini (11g) dan di sini (12c).
Selain kesalahan sintaks, skrip Anda juga mengandung kesalahan desain. Ini bukan kegagalan, tetapi praktik buruk yang seharusnya tidak menjadi kebiasaan.
- Anda belum menyebutkan sebagian besar kendala Anda. Oracle akan memberi mereka nama default tetapi itu akan menjadi nama yang mengerikan, dan membuat kamus data lebih sulit untuk dipahami. Memberi nama secara eksplisit setiap kendala membantu kami menavigasi database fisik. Ini juga mengarah ke pesan kesalahan yang lebih dapat dipahami ketika SQL kami melakukan pelanggaran kendala.
- Beri nama kendala Anda secara konsisten.
HISTORY_T
memiliki batasan yang disebuthistorys_T_FK
danfk_order_id_orders
, keduanya tidak membantu. Konvensi yang berguna adalah<child_table>_<parent_table>_fk
. Jadihistory_customer_fk
danhistory_order_fk
masing-masing. - Membuat batasan dengan pernyataan terpisah dapat berguna. Membuat tabel kemudian kunci utama kemudian kunci asing akan menghindari masalah dengan urutan ketergantungan yang diidentifikasi di atas.
- Anda mencoba membuat kunci asing siklik antara
LIBRARY_T
danFORMATS
. Anda dapat melakukan ini dengan membuat batasan dalam pernyataan terpisah tetapi jangan:Anda akan mengalami masalah saat menyisipkan baris dan bahkan masalah yang lebih buruk dengan penghapusan. Anda harus mempertimbangkan kembali model data Anda dan menemukan cara untuk memodelkan hubungan antara dua tabel sehingga yang satu adalah induk dan yang lainnya adalah anak. Atau mungkin Anda memerlukan jenis hubungan yang berbeda, seperti tabel persimpangan. - Hindari baris kosong dalam skrip Anda. Beberapa alat akan menanganinya tetapi beberapa tidak. Kita dapat mengonfigurasi SQL*Plus untuk menanganinya, tetapi lebih baik menghindari kebutuhan.
- Konvensi penamaan
LIBRARY_T
jelek. Cobalah untuk menemukan nama yang lebih ekspresif yang tidak memerlukan akhiran yang tidak perlu untuk menghindari bentrokan kata kunci. T_CUSTOMERS
bahkan lebih buruk, karena keduanya tidak konsisten dengan tabel Anda yang lain dan sama sekali tidak perlu, sebagaicustomers
bukan kata kunci.
Memberi nama sesuatu itu sulit. Anda tidak akan percaya pertengkaran yang saya alami tentang nama tabel selama bertahun-tahun. Yang terpenting adalah konsistensi. Jika saya melihat kamus data dan melihat tabel yang disebut T_CUSTOMERS
dan LIBRARY_T
tanggapan pertama saya adalah kebingungan. Mengapa tabel ini diberi nama dengan konvensi yang berbeda? Apa perbedaan konseptual ini mengungkapkan? Jadi, tolong, putuskan konvensi penamaan dan patuhi. Jadikan nama tabel Anda semua tunggal atau semua jamak. Hindari awalan dan akhiran sebanyak mungkin; kita sudah tahu itu tabel, kita tidak perlu T_
atau _TAB
.