To błaga o kłopoty. Nadal będziesz napotykać drobne niezgodności. Lub nawet nie zauważaj ich dużo później, kiedy szkoda zostanie wyrządzona. Nie rób tego. Używaj również PostgreSQL lokalnie. Jest dostępny bezpłatnie dla większości systemów operacyjnych. Dla kogoś zaangażowanego w „projekt kursu z bazami danych” jest to zaskakujące szaleństwo. Powiązane:
Inne porady:
-
Jako @Priidu wspomniany w komentarzach , twoje ograniczenia klucza obcego są wsteczne. To nie podlega dyskusji, są po prostu w błędzie .
-
W PostgreSQL użyj
serial
lubIDENTITY
kolumna (Postgres 10+) zamiast SQLiteAUTOINCREMENT
. Zobacz: -
Użyj
timestamp
(lubtimestamptz
) zamiastdatetime
. -
Nie używaj identyfikatorów wielkości liter.
-
Nie używaj nieopisowych nazw kolumn, takich jak
id
. Kiedykolwiek. To jest antywzorzec wprowadzony przez oprogramowanie pośredniczące i ORM-y. Kiedy dołączasz do kilku tabel, otrzymujesz wiele kolumn o nazwieid
. To jest aktywnie bolesne. -
Istnieje wiele stylów nazewnictwa, ale większość zgadza się, że lepiej jest używać pojedynczych terminów jako nazw tabel. Jest krótszy i przynajmniej tak samo intuicyjny/logiczny.
label
, a nielabels
.
Wszystko razem, może wyglądać tak:
CREATE TABLE IF NOT EXISTS post (
post_id serial PRIMARY KEY
, author_id integer
, title text
, content text
, image_url text
, date timestamp
);
CREATE TABLE IF NOT EXISTS label (
label_id serial PRIMARY KEY
, name text UNIQUE
);
CREATE TABLE IF NOT EXISTS label_post(
post_id integer REFERENCES post(post_id) ON UPDATE CASCADE ON DELETE CASCADE
, label_id integer REFERENCES label(label_id) ON UPDATE CASCADE ON DELETE CASCADE
, PRIMARY KEY (post_id, label_id)
);
Wyzwalacz
Aby usunąć nieużywane etykiety, zaimplementuj wyzwalacz . Dostarczam inną wersję, ponieważ nie jestem zadowolony z tej dostarczonej przez @Priidu :
CREATE OR REPLACE FUNCTION f_trg_kill_orphaned_label()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
DELETE FROM label l
WHERE l.label_id = OLD.label_id
AND NOT EXISTS (
SELECT 1 FROM label_post lp
WHERE lp.label_id = OLD.label_id
);
END
$func$;
-
funkcja wyzwalacza należy utworzyć przed wyzwalacz .
-
Proste
DELETE
polecenie może wykonać zadanie. Nie potrzeba drugiego zapytania - w szczególności nie macount(*)
.EXISTS
jest tańszy. -
Pojedyncze cudzysłowy wokół nazwy języka są tolerowane, ale tak naprawdę jest to identyfikator, więc po prostu pomiń nonsens:
LANGUAGE plpgsql
CREATE TRIGGER label_post_delaft_kill_orphaned_label
AFTER DELETE ON label_post
FOR EACH ROW EXECUTE PROCEDURE f_trg_kill_orphaned_label();
Nie ma CREATE OR REPLACE TRIGGER
w PostgreSQL. Po prostu CREATE TRIGGER
.