Nekromancja.
Prawidłowa odpowiedź to: zależy od silnika bazy danych i narzędzia zarządzania.
Zróbmy przykład:
mamy tabelę raportów,
a raport może mieć element nadrzędny (punkt menu, podobny do kategorii),
a ten element nadrzędny może mieć element nadrzędny (np. Centrum zysków)
i tak dalej w nieskończoność.
Najprostszy przykład standardowej relacji rekurencyjnej, tak jak w przypadku każdej jednostki / hierarchii odwołującej się do siebie.
Wynikowa tabela SQL-Server to:
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'dbo.FK_T_FMS_Reports_T_FMS_Reports') AND parent_object_id = OBJECT_ID(N'dbo.T_FMS_Reports'))
ALTER TABLE dbo.T_FMS_Reports DROP CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.T_FMS_Reports') AND type in (N'U'))
DROP TABLE dbo.T_FMS_Reports
GO
CREATE TABLE dbo.T_FMS_Reports
(
RE_UID uniqueidentifier NOT NULL
,RE_RE_UID uniqueidentifier NULL
,RE_Text nvarchar(255) NULL
,RE_Link nvarchar(400) NULL
,RE_Sort int NOT NULL
,RE_Status int NOT NULL
,PRIMARY KEY CLUSTERED ( RE_UID )
);
GO
ALTER TABLE dbo.T_FMS_Reports WITH CHECK ADD CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports FOREIGN KEY(RE_RE_UID)
REFERENCES dbo.T_FMS_Reports (RE_UID)
-- ON DELETE CASCADE -- here, MS-SQL has a problem
GO
ALTER TABLE dbo.T_FMS_Reports CHECK CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports
GO
Ale pojawia się problem:
gdy trzeba usunąć menupunkt ze wszystkimi jego podmenu, NIE MOŻESZ ustawić kaskady usuwania, ponieważ Microsoft SQL Server nie obsługuje rekurencyjnych kasowanych kasowań (z drugiej strony PostGreSQL nie robi tego (ale tylko jeśli graph nie jest cykliczny], podczas gdy MySQL w ogóle nie lubi tego rodzaju struktury tabel, ponieważ nie obsługuje rekurencyjnych CTE).
W ten sposób wysadzasz z nim integralność usuwania / funkcjonalność, co powoduje, że obowiązkowe jest wdrożenie takiej funkcjonalności we własnym kodzie lub w procedurze przechowywanej (jeśli RDBMS obsługuje procedury przechowywane).
To bez wątpienia wysadzi jakikolwiek w pełni automatyczny import / eksport danych dynamicznych, ponieważ nie można po prostu uruchomić instrukcji usuwania dla wszystkich tabel zgodnie z relacjami klucza obcego (nie odwołując się do siebie), ani nie można wykonać prostego wyboru * i utwórz wstawkę dla każdego wiersza w dowolnej kolejności.
Na przykład, gdy tworzysz skrypt INSERT za pomocą SSMS, wówczas SSMS nie otrzyma klucza obcego, a zatem faktycznie tworzy instrukcje insert, które wstawią wpisy z zależnościami, zanim wstawią element nadrzędny zależności, co zakończy się błędem , ponieważ klucz obcy jest na swoim miejscu.
Jednak przy odpowiednich systemach zarządzania bazami danych (takich jak PostgreSQL), z odpowiednim oprzyrządowaniem, nie powinno to stanowić problemu. Po prostu rozumiem, że tylko dlatego, że płacisz dużo za RDBMS (patrzę na ciebie, Microsoft; Oracle =?) I / lub jego pasek narzędzi, nie oznacza to, że jest odpowiednio zaprogramowany. I OpenSource (np. MySQL) nie czyni cię odpornym na tak wspaniałe drobiazgi.
Diabeł tkwi w szczegółach, jak mówi stare przysłowie.
Teraz nie jest tak, że nie możesz obejść takich problemów, ale naprawdę nie poleciłbym tego, jeśli twój system będzie złożony (np. Ponad 200 tabel).
Co więcej, w zwykłym komercyjnym otoczeniu (jak to przedstawił Dilbert), po prostu nie otrzymasz tego czasu.
O wiele lepszym podejściem, choć trudniejszym, byłby stół zamykający.
Miałoby to dodatkową zaletę, że działa również na MySQL.
Gdy raz zaimplementujesz funkcję zamykania, będziesz w stanie działać w dodatkowych miejscach w niemalże żadnym momencie.