Kami menemukan diri kami di artikel ketiga dalam seri migrasi Oracle. Kali ini, kita melihat operator aneh yang memodifikasi kriteria klausa WHERE di Oracle (+). Seperti yang lainnya, PostgreSQL memiliki solusi untuk itu.
GABUNG KANAN
Oracle mendukung, dan banyak pengembang menggunakan, sintaks ANSI outer JOIN menggunakan operator ke klausa kualifikasi.
Biasanya, itu terlihat seperti ini:
SELECT *
FROM person, places
WHERE person.id = places.person_id(+)
Tujuan dari sintaks ini adalah gabungan luar kanan. Dalam istilah teori himpunan, ini adalah himpunan bagian yang mencakup semua tempat, terlepas dari orangnya.
Hasil dari sampel kecil akan terlihat seperti ini:
id | nama_belakang | nama_depan | id | lokasi | person_id |
---|---|---|---|---|---|
1 | (NULL) | (NULL) | 1 | Dallas | (NULL) |
2 | Roybal | Kirk | 2 | London | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
Sintaks ini tidak didukung di PostgreSQL.
Untuk mencapai hasil yang sama, Anda akan menggunakan sintaks SQL standar untuk gabungan luar.
SELECT *
FROM persons
RIGHT JOIN places
ON persons.id = places.person_id;
SQL juga menyediakan keterangan klarifikasi OUTER
. Clarifier ini sepenuhnya opsional, karena setiap RIGHT JOIN
menurut definisi adalah OUTER
bergabung.
GABUNG LENGKAP
Demikian pula, menggunakan sintaks Oracle untuk bergabung penuh tidak berfungsi di PostgreSQL.
SELECT *
FROM persons, places
WHERE persons.id(+) = places(+);
Tujuan dari sintaks ini adalah daftar lengkap orang dan tempat apakah seseorang diasosiasikan dengan suatu tempat atau tidak.
Hasilnya akan seperti ini:
id | nama_belakang | nama_pertama** | id | lokasi | person_id |
---|---|---|---|---|---|
1 | (NULL) | (NULL) | 1 | Dallas | (NULL) |
2 | Roybal | Kirk | 2 | London | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
4 | Andrew | Ganteng | (NULL) | (NULL) | (NULL) |
Menggunakan sintaks PostgreSQL, kueri akan ditulis sebagai berikut:
SELECT *
FROM persons
FULL JOIN places
ON persons.id = places.person_id;
Sekali lagi, OUTER
kata kunci sepenuhnya opsional.
GABUNG LINTAS
Salah satu keuntungan berbeda dari pendekatan menggunakan kata kunci daripada hubungan implisit adalah Anda tidak dapat membuat produk silang secara tidak sengaja.
Sintaksnya:
SELECT *
FROM persons
LEFT JOIN places;
Akan menghasilkan kesalahan:
ERROR: syntax error at or near ";"
Menunjukkan bahwa pernyataan tidak lengkap pada penanda akhir baris “;”.
PostgreSQL akan membuat produk gabungan silang menggunakan sintaks ANSI.
SELECT *
FROM persons, places;
id | nama_belakang | nama_depan | id | lokasi | person_id |
---|---|---|---|---|---|
1 | Sialan | Andrew | 1 | Dallas | (null) |
1 | Sialan | Andrew | 2 | London | 2 |
1 | Sialan | Andrew | 3 | Paris | 3 |
1 | Sialan | Andrew | 4 | Madrid | (null) |
2 | Kerajaan | Kirk | 1 | Dallas | (null) |
2 | Kerajaan | Kirk | 2 | London | 2 |
2 | Kerajaan | Kirk | 3 | Paris | 3 |
2 | Kerajaan | Kirk | 4 | Madrid | (null) |
3 | Riggs | Simon | 1 | Dallas | (null) |
3 | Riggs | Simon | 2 | London | 2 |
3 | Riggs | Simon | 3 | Paris | 3 |
3 | Riggs | Simon | 4 | Madrid | (null) |
6 | Wong | Tandai | 1 | Dallas | (null) |
6 | Wong | Tandai | 2 | London | 2 |
6 | Wong | Tandai | 3 | Paris | 3 |
6 | Wong | Tandai | 4 | Madrid | (null) |
Yang lebih mungkin merupakan kesalahan pengkodean daripada hasil yang disengaja.
Untuk mendapatkan fungsi ini dengan sengaja, disarankan untuk menggunakan CROSS JOIN
pernyataan.
SELECT *
FROM persons
CROSS JOIN places;
Dengan demikian memperjelas apa yang dimaksud dalam pernyataan tersebut.
GABUNG ALAMI
PostgreSQL mendukung NATURAL JOIN
sintaks, tetapi sedikit diprotes.
SELECT *
FROM persons
NATURAL JOIN places;
Ini menghasilkan hasil berikut.
id | nama_belakang | nama_depan | induk_id | lokasi | person_id |
---|---|---|---|---|---|
1 | Sialan | Andrew | (null) | Dallas | (null) |
2 | Kerajaan | Kirk | 1 | London | 2 |
3 | Riggs | Simon | 1 | Paris | 3 |
Namun, sintaks ini adalah masalah. Untuk contoh kita, kolom “id” di kedua tabel tidak ada hubungannya satu sama lain . Penggabungan ini telah membuahkan hasil, tetapi hasil dengan konten yang sama sekali tidak relevan.
Selain itu, Anda mungkin memiliki kueri yang awalnya menyajikan hasil yang benar, tetapi pernyataan DDL berikutnya diam-diam memengaruhi.
Pertimbangkan:
ALTER TABLE person ADD COLUMN places_id bigint;
ALTER TABLE places ADD COLUMN places_id bigint;
ALTER TABLE person ADD COLUMN person_id bigint;
Sekarang kolom apa NATURAL JOIN
menggunakan? Pilihannya adalah id, place_id, person_id, dan semuanya di atas. Saya akan menyerahkan jawabannya sebagai latihan kepada pembaca.
Sintaks ini adalah bom waktu untuk kode Anda. Jangan menggunakannya.
Oke, jadi Anda tidak yakin. Nah, maka setidaknya memiliki beberapa konvensi pengkodean yang waras. Untuk tabel induk, beri nama kolom identitas “myparenttable_id”. Saat mereferensikannya dari relasi anak, gunakan nama yang sama, “myparenttable_id”. Jangan pernah menamai apapun dengan “id”, dan jangan pernah membuat referensi ke kolom dengan nama yang berbeda. Ah, lupakan saja. Jangan lakukan ini.
Anda mungkin tergoda untuk mengaburkan teka-teki sebelumnya dengan menggunakan USING
kata kunci. Itu akan terlihat seperti ini:
SELECT *
FROM persons
JOIN places
USING (id);
Tapi USING
kata kunci hanya dapat memanfaatkan kecocokan nama yang tepat di seluruh tabel. Yang sekali lagi, dalam contoh kita benar-benar salah.
Pilihan praktik terbaik untuk PostgreSQL adalah menghindari mendesain tabel dengan mengkodekan standar konvensi.
Ringkasan
Teknik kata kunci ini (vs. operator) juga tersedia di Oracle. Mereka lebih lintas platform, dan kurang ambigu. Itu saja akan membuat mereka menjadi praktik terbaik.
Selain itu, mereka mengekspos kesalahan logis ketika digunakan secara tidak benar. Untuk pengembangan apa pun di PostgreSQL, kami merekomendasikan penggunaan kata kunci eksplisit secara sepihak.