Foreign key – przypadek szefa wszystkich szefów

0

Witam.
Poniżej diagram tabel dla mojej bazy danych :

screen.png

Idea tabeli Workers_Office jest taka :
Jeden pracownik może pracować na kilku stanowiskach i ma swojego przełożonego, który jest w bazie przechowywany jak normalny pracownik, tylko o innym stanowisku.
Tylko jak rozwiązać sytuację, gdy dojdę do szefa wszystkich szefów ? Nie mogę wrzucić nulla na miejsce foreign key. Jak rozwiązać tą sytuację ? Czy na superiorID dać ID szefa i przy zapytaniach sprawdzać czy WorkerID != superiorID ?

Pozdrawiam

2

A dlaczego nie możesz tam dać nulla? Co Cie powstrzymuje? Robisz allow null na tej kolumnie i tyle. Pracownik który ma tam nulla jest szefem wszystkich szefów.

0

To, co pisał @axelbest na pewno jest to lepsze, niż warunek, w którym jeśli ID pracownika jest równe ID szefa, to dana osoba jest szefem. Potem wystarczy jakaś pomyłka i nagle będziemy mieli samych szefów ;) Aczkolwiek co do nulla to też nie jestem przekonany, bo analogicznie - jeśli przy dodawaniu nie umieścisz (całkowicie pomyłkowo) wartości przełożonego, to znowu będziesz miał wysyp prezesów.

Ja bym zdefiniował coś w stylu "ID = 9999999" i to zarezerwował dla Szefa. Raczej małe są szanse, że AUTO_INCREMENT dojdzie do takiej wartości. I po prostu - dodając pracownika, jako ID szefa wstawiasz ID jego przełożonego. A "szef wszystkich szefów" jako swojego przełożonego będzie miał wpisane "9999999". Proste i skuteczne.

Zastanawia mnie coś innego - piszesz, że jeden pracownik może pracować na kilku stanowiskach. Czy w związku z tym będzie miał kilku przełożonych? Zastanów się, jak to ma wyglądać (nie od strony bazy, ale "po ludzku", bo widzę tutaj pewne ryzyko zakręcenia się).

EDIT: jak słusznie ludzie zauważyli - nie przejdzie to w przypadku stosowania FOREIGN KEY. Moje przeoczenie :(

2

Ja bym zdefiniował coś w stylu "ID = 9999999" i to zarezerwował dla Szefa.

Huh? Co jest nie tak z nullem?
Przynajmniej nie jest tak arbitralny jak 99999999 i nie wymaga trzymania w kodzie magicznych liczb wyciągniętych znikąd.

1

Huh? Co jest nie tak z nullem?

To, że dodając pracownika, jeśli omyłkowo nie podasz ID przełożonego, a do tego masz na bazie dopuszczone nulle, to taki wpis przejdzie bez zastrzeżeń i w efekcie powstaną kolejni prezesi, czego nie chcemy.

Co do 999999 - to był taki przykład. Rozwijając myśl - definiujesz gdzieś jakąś stałą w stylu SUPERSZEF = 9999999 i wszędzie gdzie trzeba, zamiast sprawdzać, czy Id_przelozonego = null, robisz sprawdzenie if (Id_przelozonego == SUPERSZEF).

EDIT: jak słusznie ludzie zauważyli - nie przejdzie to w przypadku stosowania FOREIGN KEY. Moje przeoczenie :(

3

To, że dodając pracownika, jeśli omyłkowo nie podasz ID przełożonego, a do tego masz na bazie dopuszczone nulle, to taki wpis przejdzie bez zastrzeżeń i w efekcie powstaną kolejni prezesi, czego nie chcemy.

W przypadku, gdy ręcznie piszesz SQLe - jak najbardziej :-)

Można to jednak zawsze obsłużyć sensownie po stronie aplikacji - a nawet jeśli będzie jakiś bug i zaczną powstawać dodatkowi szefowie, znalezienie błędu będzie stosunkowo proste w porównaniu do sytuacji, w której ktoś najpierw będzie próbował odnaleźć pracownika o id 9999999, a po kilku godzinach przeklinania dopyta Mietka, który siedzi w projekcie dłużej, i dopiero ten mu powie, że aaaa no wiesz, to takie magic number - oznacza brak szefa.

Zauważ też, że:

  1. Swoim sposobem sprawiasz, iż wejście i zrozumienie kodu jest znacznie trudniejsze, ponieważ to null jest w takim przypadku oczekiwane, nie 9999999 czy 0xdeadbeef.
  2. Twój sposób wymaga pozbycia się foreign key constraint, ponieważ - naturalnie - nie ma rekordu o id 9999999, zatem taki FK nie może istnieć.

W wypadku nulla ciężko jest ocenić, czy to jest celowo wstawiona wartość null, czy wynik przeoczenia.

No tak, widząc rekord odwołujący się do innego, nieistniejącego rekordu (o id 9999999) wcale nie można pomyśleć, że to wynik przeoczenia albo jakiegoś integer overflow ;-)

2

to jeszcze wytłumacz jak przy id = 999999 i braku pracownika z takim id ma to zadziałać (FK nie może wskazywać na nieistniejący rekord)? A jeśli taki pracownik będzie założony to jaki on będzie miał id_szefa? 9999999? a ten będzie miał id_szefa 99999999 i tak aż się nam zakres skończy?

Pracownik - szef to klasyczne drzewko i jako takie, dla głównej gałęzi id_up wstawia się null i nic się nie kombinuje.

2

W takiej sytuacji można dodać rekord z ID = 0. I wtedy ten szef wszystkich szefów ma ID szefa = 0. A to z racji tego, żeby nie rozróżniać podczas pisania zapytań pola null którego się sprawdza inaczej (is null). Przy założeniu, że dajemy zero, mamy rekord z ID = 0. Klucze zewnętrzne pracują, zapytania też można pisać ze zwykłym join, a nie np left join. O wiele lepsze niż jakieś magiczne 99999 które może z czasem kolidować z rosnącym ID.

2

@Mr.YaHooo: A jak będziesz miał szefa i vice szefa? Jak będziesz miał szefów np w oddziale polskim i zagranicznym? Nadal kiepskie rozwiązanie. Czego tak się boicie tego nulla?

Skoro szef nie ma przełożonego to jego szefem jest null i tyle.

0
axelbest napisał(a):

Czego tak się boicie tego nulla?

Nie boję się, tylko wyszukiwanie jest po prostu wygodniejsze. Łatwo można wtedy do wyszukiwania użyć zapytania z parametrem typu:

select * from employers where superior_id = :sup_id

Jeśli w programie mam okno z wykazem pracowników oraz możliwością zawężania do danego szefa lub bez pracownika nadrzędnego, to załatwię to jednym sparametryzowanym selectem. Jeśli będzie null będzie trochę gimnastyki bez zmiany zapytania. Chyba, że nie jestem w stanie odnaleźć prostego rozwiązania.

axelbest napisał(a):

Jak będziesz miał szefów np w oddziale polskim i zagranicznym?

A jak tą sprawę rozwiązuje null w polu?

0

I pisałbyś takie zapytanie z palca, czy też dał do wykonania ORMowi, który przewiduje takie przypadki i sam dopisuje is null? ;-)

0

@Patryk27 cóż ja tam wolę mieć kontrolę nad zapytaniami :]

A tak na serio faktycznie jeśli ktoś używa ORM (ja nie, ale to nie temat na dyskusję) to faktycznie null będzie lepszym rozwiązaniem. W przypadku braku ORM'a moja propozycja wydaje się ułatwiać pisanie zapytań.

1 użytkowników online, w tym zalogowanych: 0, gości: 1