Foreign key – przypadek szefa wszystkich szefów

Odpowiedz Nowy wątek
2018-06-10 23:40
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

edytowany 3x, ostatnio: furious programming, 2018-06-10 23:47
screena brak - Burdzi0 2018-06-10 23:46
Już jest - kenik 2018-06-10 23:47
@kenik: poprawiłem wątek. Zrzuty dodajemy do załączników, a tytuł nadajemy taki, aby w skrócie opisywał poruszany problem. Zapamiętaj na przyszłość. - furious programming 2018-06-10 23:48

Pozostało 580 znaków

2018-06-11 05:44

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.

Zastanawiałem się czy to jest sensowne rozwiązanie ;) Dziękuję za odpowiedź. - kenik 2018-06-11 09:06

Pozostało 580 znaków

2018-06-11 09:16
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 :(


That game of life is hard to play, I'm gonna lose it anyway, The losing card I'll someday lay, So this is all I have to say
edytowany 1x, ostatnio: cerrato, 2018-06-11 16:20
Zgadza się, może mieć kilku przełożonych. Oczywiście wiadomo, że mało kto przekroczy liczbę 2, bo może pracować na 2 stanowiskach i się może złożyć, że będzie miał różnych przełożonych. - kenik 2018-06-11 09:23
No to pytanie - rozumiem, że dla każdego stanowiska tworzysz osobny wpis w bazie? Znaczy - będzie ten sam "Jaś Kowalski" wpisany - raz jako tynkarz z szefem o ID=34, a drugi raz jako malarz z szefem o ID=22? - cerrato 2018-06-11 09:25
Znaczy tabela Worker zostanie utworzona raz, ale Worker_Office już 2 razy, bo będzie miał inną datę zatrudnienia lub przełożonego czy pensję. - kenik 2018-06-11 09:26
Ja bym zdefiniował coś w stylu "ID = 9999999" wtff - WeiXiao 2018-06-13 18:22

Pozostało 580 znaków

2018-06-11 09:19
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.


edytowany 1x, ostatnio: Patryk27, 2018-06-11 09:19
Null oznaczał drzewiej "brak danych" albo "wartość nieokreślona/brakująca" - w tym wypadku nie zachodzi żaden z tych dwóch scenariuszy. - loza_szydercow 2018-06-11 16:16
Nawet w aktualnej dokumentacji MySQLa (https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html) widnieje Conceptually, NULL means “a missing unknown value” (...). Tym niemniej, odchodząc od semantyki stricte, wydaje mi się, że schemat budowy drzewa z rodzicami oznaczonymi poprzez parent_id = null jest obecnie najpopularniejszym i najczytelniejszym podejściem - nie trzeba się martwić z arbitralnymi idkami, które kiedyś mogą skolidować, czy też nie ma problemu z kluczami obcymi. Jaką alternatywę byś proponował, jeśli nie null? - Patryk27 2018-06-11 17:40
Szczerze mówiąc to nie chciało mi się za bardzo tego rozkminiać bo bardzo dawno nie bawiłem się w SQLa. Owszem struktury drzewiaste implementowało się przez nulle - wtedy mnie to nie dziwiło. Zastanawiałem się głównie nad rozwiązaniem @Mr.YaHooo bo jest czytelne - obiekt wskazuje na samego siebie, czyli ty jesteś swoim szefem, dobry terminator. Tylko nie chciało mi się sprawdzać jak wygląda to od strony SQLa - czyli jak wygląda zapytanie w stosunku do tego z nullem :/ - loza_szydercow 2018-06-12 21:22

Pozostało 580 znaków

2018-06-11 09:23
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 :(


That game of life is hard to play, I'm gonna lose it anyway, The losing card I'll someday lay, So this is all I have to say
edytowany 1x, ostatnio: cerrato, 2018-06-11 16:20
Znaczy przy dodawaniu pracowników planuję wybierać typ stanowiska, więc jak wybiorę typ stanowiska jako szef wszystkich szefów, to automatycznie logika zapewni wstawienie nulla w tym miejscu. - kenik 2018-06-11 09:24
Jak pisałem - moim zdaniem lepiej jest ŚWIADOMIE wstawić jakąś wartość - wtedy masz większe szanse, że nie jest to wynik błędu. W wypadku nulla ciężko jest ocenić, czy to jest celowo wstawiona wartość null, czy wynik przeoczenia. Jeśli jesteś pewien, że błedu nie będzie - niech będzie ten null, aczkolwiek jakaś zdefiniowana wcześniej wartość w mojej ocenie jest pewniejsza (i ja bym tak zrobił). - cerrato 2018-06-11 09:26

Pozostało 580 znaków

2018-06-11 11:34
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 ;-)


edytowany 4x, ostatnio: Patryk27, 2018-06-11 11:38
Dobrze prawisz :) - axelbest 2018-06-11 11:47
"Twój sposób wymaga pozbycia się foreign key constraint" - tutaj masz całkowitą rację, zapomniałem o tym szczególe :( - cerrato 2018-06-11 12:14

Pozostało 580 znaków

2018-06-11 14:10
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.


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
napisałem w komentarzu do poprzedniego posta - "Twój sposób wymaga pozbycia się foreign key constraint" - tutaj masz całkowitą rację, zapomniałem o tym szczególe. - cerrato 2018-06-11 16:15

Pozostało 580 znaków

2018-06-12 17:54
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.

Pozostało 580 znaków

2018-06-12 23:09
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.

Pozostało 580 znaków

2018-06-13 16:44
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?

Pozostało 580 znaków

2018-06-13 16:59
0

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


edytowany 1x, ostatnio: Patryk27, 2018-06-13 16:59

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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