Šajā rakstā detalizēti paskatīsimies uz diviem no tabulu kombinēšanas veidiem – Natural Join un Named Columns Join jeb Using klauzu.
For english speaking only check SQL join types.
Dabiskais savienojums
Dabiskais savienojums kombinē divu tabulu datus ar speciālu nosacījumu – tiek salīdzinātas abu tabulu kolonas, kuriem ir vienādi nosaukumi. Līdz ar to kombinēšanas nosacījums ir apslēpts un atkarīgs no tabulu struktūras izpildes brīdī. Šāds vaicājumu rakstīšanas veids, protams, rada potenciālas briesmas nākotnē – tajā brīdi, kad tabulu struktūra pamainīsies, rezultāti var kļūt nekorekti par spīti tam, ka vaicājums sintaktiski ir pareizs.
Sintakse
SELECT <kolonu saraksts> FROM <kreisās puses tabula> NATURAL <kombinēšanas tips> JOIN <labās puses tabula>
Kombinēšanas tips var būt viens no:
- Tukšs – tādā gadījumā tas ir tas pats INNER;
- INNER;
- LEFT [OUTER] – vārdu OUTER var nelietot;
- RIGHT [OUTER] – vārdu OUTER var nelietot;
- FULL [OUTER] – vārdu OUTER var nelietot.
SELECT un FROM klauzas ir aprakstītas iepriekšējā tēmā Vienkāršs SQL Select teikums.
Kā jau redzams no kombinēšanas tipiem, nekas jauns no saturiskā viedokļa klāt nav nācis. Tas ir tas pats iekšējais savienojums un tie paši vairāki ārējā savienojuma veidi, kas aprakstīti jau iepriekš. Šis ir tikai cits sintaktisks veids, kā to pierakstīt. Tā kā tiek salīdzinātas tās divu tabulu kolonas, kuru nosaukumi sakrīt, tad iepriekšējie piemēri neder, jo tur katrā tabulā bija savs atšķirīgs kolonu prefikss. Tādēļ piemēriem šeit citas tabulas:
CREATE TABLE valstis ( valsts_id INTEGER NOT NULL PRIMARY KEY, valsts VARCHAR2(40) NOT NULL); CREATE TABLE pilsetas ( pils_id INTEGER NOT NULL PRIMARY KEY, valsts_id INTEGER, pilseta VARCHAR2(40) NOT NULL); CREATE TABLE vietas ( viet_id INTEGER NOT NULL PRIMARY KEY, pils_id INTEGER, teksts VARCHAR2(40) NOT NULL); INSERT INTO valstis VALUES (1, 'LATVIJA'); INSERT INTO valstis VALUES (2, 'IGAUNIJA'); INSERT INTO pilsetas VALUES (1, 1, 'RĪGA'); INSERT INTO pilsetas VALUES (2, 1, 'LIEPĀJA'); INSERT INTO pilsetas VALUES (3, 2, 'TARTU'); INSERT INTO vietas VALUES (1, 1, 'MEŽAPARKS'); INSERT INTO vietas VALUES (2, 2, 'KARA OSTA');
Piemērs 1. Atlasa valstu un pilsētu nosaukumus izmantojot Natural Inner join sintaksi.
SQL> SELECT valsts, pilseta FROM valstis NATURAL JOIN pilsetas; VALSTS PILSETA -------- --------- LATVIJA RĪGA LATVIJA LIEPĀJA IGAUNIJA TARTU
Piemērs 2. Atlasa pilsētas nosaukumu un vietas tekstu izmantojot Left Outer join un saglabājot pilsētas.
SQL> SELECT pilseta, teksts FROM pilsetas NATURAL LEFT JOIN vietas; PILSETA TEKSTS ---------------------------------------- --------------------------- RĪGA MEŽAPARKS LIEPĀJA KARA OSTA TARTU
Ja tabulām kopīga nosaukuma kolonas nav, tad Natural Join rezultāts ir Dekarta reizinājums.
Piemērs 3. Atlasa datus no valstīm un vietām, rezultātā iegūstot Dekarta reizinājumu.
SQL> SELECT valsts, teksts FROM valstis NATURAL JOIN vietas; VALSTS TEKSTS ---------------------------------------- -------------------- LATVIJA MEŽAPARKS LATVIJA KARA OSTA IGAUNIJA MEŽAPARKS IGAUNIJA KARA OSTA
Tātad tiklīdz pamanāmies pielikt klāt papildus tāda paša nosaukuma kolonas, kā ir otrā tabulā, tā kombinēšanas nosacījums ietver jau divas kolonas un, protams, ne vienmēr tas ir pareizi. Nākošā piemērā redzams, ka pirmais piemērs nestrādā tā kā mēs droši vien vēlētos, jo kombinēšanas nosacījums ietver arī jauno kolonu komentars. Tā kā šīs kolonas saturs ir NULL un praktiski nekad arī nesakritīs, tad rezultāts arī vienmēr būs ne tas, ko parasti cilvēki iedomājas.
Piemērs 4. Papildinam tabulu pilsetas un tabulu valstis ar jaunu kolonu komentārs un izpildam pirmajā piemērā redzamo SQL vaicājumu.
SQL> ALTER TABLE pilsetas ADD komentars VARCHAR2(500); Table altered. SQL> ALTER TABLE valstis ADD komentars VARCHAR2(500); Table altered. SQL> SELECT valsts, pilseta FROM valstis NATURAL JOIN pilsetas; no rows selected
Nosaukto kolonu savienojums
Šis sintakses veids iet mazliet tālāk nekā dabiskā savienojuma sintakse un ļauj norādīt kolonas, pēc kurām veikt savienojumu. Līdz ar to tas nav tik bīstams. Sintakse nosaukto kolonu savienojumam ir šāda:
SELECT <kolonu saraksts> FROM <kreisās puses tabula> <kombinēšanas tips> JOIN <labās puses tabula> USING (<kolonu uzskaitījums>)
Kombinēšanas tipi ir tieši tie paši kas jau uzskaitīti augstāk pie Natural join. Kolonu uzskaitījumā tiek uzskaitītas kolonas, pēc kurām jāveic salīdzināšana, atdalītas ar komatu. Līdz ar to mēs varam pārrakstīt un uzlabot 4. piemēru tā, ka tas tagad strādā tā kā mēs to vēlētos, izmantojot nosaukto kolonu savienojumu:
Piemērs 5. Izpildam pirmajā un ceturtajā piemērā redzamo SQL pieprasījumu izmantojot Using klauzu.
SQL> SELECT valsts, pilseta FROM valstis 2 JOIN pilsetas USING (valsts_id); VALSTS PILSETA ---------------------------------------- --------- LATVIJA RĪGA LATVIJA LIEPĀJA IGAUNIJA TARTU
Protams varam paniekoties un izmantot šo sintaksi kombinējot pēc komentāra kolonas, bet šoreiz lietojot Full outer join.
Piemērs 6. Kombinējam ierakstus no valstīm un pilsētām izmantojot kolonu komentars un pilnu ārējo savienojumu.
SQL> SELECT valsts, pilseta FROM valstis 2 FULL OUTER JOIN pilsetas USING (komentars); VALSTS PILSETA ---------------------------------------- --------- IGAUNIJA LATVIJA TARTU LIEPĀJA RĪGA
Kas jāatceras papildus:
- Ja vien jums nav vēlmes iekodēt SQL kodā bumbas ar laika degli vai nodarboties ar neuzturama koda rakstīšanu, tad izlasiet šo rakstu un aizmirstiet par šiem sintakses veidiem, jo sevišķi par Natural Join. Vai teiksim atcerieties, ka tādi ir, bet lietojiet tikai tad, ja ir vēlme kādam ieriebt 😉
- Šie kombinēšanas sintakses veidi ļauj kombinēt datus no tabulām tikai un vienīgi izmantojot vienādības nosacījumu.
- USING klauzā var izmantot tikai un vienīgi tādas kolonas, kas ir abās tabulās.
Turpmākā lasāmviela
- Natural Joins are Evil – apraksts par dabisko savienojumu negatīvajām īpašībām.