Uczymy się czym tak naprawdę jest klucz obcy. Większość poznamy w tej lekcji, nieco więcej w następnej. Do dzieła.
Ok, idziemy do tabeli reviews, do structure. Widzimy, że movie_id to bigint 20 unsigned not null. Taki sam typ ma id w movies. Tak, jeżeli chcemy porównywać ze sobą id, robić joiny, to kolumna odnosząca się do innej tabeli musi być tego samego typu.
To oczywiście nie znaczy jeszcze, że movie_id jest kluczem obcym. Wejdźmy w relacyjny widok, tak zobaczymy:
- constraint name reviews_movie_id
- on delete cascade
- on update restrict
- column movie_id
- table movies
- column id
I to oznacza, że do reviews nie wrzucimy recenzji mającej movie_id, który w movies w kolumnie id nie istnieje. Plus kilka innych rzeczy, zaraz to ogarniemy.
Ok, skaczemy do innej bazy danych, gdzie poprzednio zrobiliśmy sobie coś takiego:
CREATE TABLE `people` (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT UNSIGNED NOT NULL,
PRIMARY KEY(id)
);
INSERT INTO `people` (name, age)
VALUES("John Doe", 33);
INSERT INTO `people` (name, age)
VALUES("Jane Doe", 33);
INSERT INTO `people` (name, age)
VALUES("Jim Doe", 33);
Mam nadzieję, że jeszcze to pamiętamy. Teraz tworzymy tabelkę:
CREATE TABLE `contacts` (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
person_id BIGINT UNSIGNED NOT NULL,
city VARCHAR(255) NOT NULL,
street VARCHAR(255) NOT NULL,
PRIMARY KEY(id)
);
Ta tabelka nie ma klucza obcego. Ma tylko pole person_id, którego typ zgadza się z polem id w tabeli people. To wystarczy, aby robić joiny.
Najpierw dodajmy sobie to i owo:
INSERT INTO `contacts` (person_id, city, street)
VALUES(1, "London", "London Street");
INSERT INTO `contacts` (person_id, city, street)
VALUES(2, "Warsaw", "Warsaw Street");
INSERT INTO `contacts` (person_id, city, street)
VALUES(3, "Warsaw", "Warsaw Street");
Ok, teraz join:
SELECT * FROM `people` AS p
LEFT JOIN `contacts` AS c
ON p.id = c.person_id;
Fajnie to wygląda. Ale zobaczmy na ten kod:
UPDATE `contacts`
SET `person_id` = '4'
WHERE `contacts`.`id` = 3;
Nie ma osoby z id 4 a taki person_id przypisaliśmy ostatniemu adresowi. Mało tego, dodajmy:
INSERT INTO `contacts`
(person_id, city, street)
VALUES
(30, "Warsaw", "Warsaw Street");
Nie ma osoby z ID 30 a taki person_id sobie brutalnie dodaliśmy do contacts. Właśnie dlatego używamy kluczy obcych.
Utwórzmy taką tabelkę:
CREATE TABLE `addresses` (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
person_id BIGINT UNSIGNED NOT NULL,
city VARCHAR(255) NOT NULL,
street VARCHAR(255) NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (person_id) REFERENCES people(id)
);
Jak rzucimy okiem na widok relacyjny to jesteśmy już blisko zrozumienia tego, co laravel nam robi automatycznie w naszej bazie danych.
Spróbujmy dodać coś, co nie istnieje:
INSERT INTO `addresses` (person_id, city, street)
VALUES(10, "London", "London Street");
#fail
Foreign key constraint error, czyli koszmar ludzi, którzy zaczęli używać ORMa bez rozumienia czystego SQLa. Albo inaczej – próbujesz jako person_id mi 10 ustawić, ale w tabeli people nie ma id o wartości 10.
Ok, dodajmy „legitne” numery id:
INSERT INTO `addresses`
(person_id, city, street)
VALUES
(1, "London", "London Street");
INSERT INTO `addresses`
(person_id, city, street)
VALUES
(2, "Warsaw", "Warsaw Street");
INSERT INTO `addresses`
(person_id, city, street)
VALUES
(3, "Warsaw", "Warsaw Street");
Teraz zróbmy left-join, bo choć tak nie jest, mogłoby tak być, że jakaś osoba (tabela po prawej) nie ma adresu (tabela po lewej), ale to jeszcze nie powód, aby osobę z result setu usuwać tylko dlatego, że adresu nie ma:
SELECT * FROM `people` AS p
LEFT JOIN `addresses` AS a
ON p.id = a.person_id;
Właściwie to możemy dodać osobę bez adresu:
INSERT INTO `people` (name, age)
VALUES("Tim Homeless", 33);
Teraz left join będzie pokazywał pana bezdomnego, ale już join nie:
SELECT *
FROM `people` AS p
JOIN `addresses` AS a
ON p.id = a.person_id;
Jeszcze kilka zagadnień musimy lepiej poznać, ale już na dobrej drodze jesteśmy.