MySQL pytanie początkującego

0

Witam wszystkich,

na wstępie muszę napisać, że z MYSQL jestem samoukiem- pomimo, że mam teraz taki kurs na studiach. Mam do zrealizowania projekt- stworzyć bazę danych dotyczącą sprzedaży biletów do kina. Nie wiem jak rozwiązać jedną kwestię. Ilość miejsc w sali kinowej jest ograniczona- powiedzmy, że jest ich 50. W jaki sposób uwzględnić to, aby na konkretny seans nie sprzedać więcej biletów niż jest miejsc i aby nie sprzedać 2 biletów na to samo miejsce?

Utworzyłem 4 tabele- jedna z seansami, druga z klientami - gdzie podany jest numer biletu, data seansu i numer miejsca, tabelę z miejscami w sali i tabelę ze sprzedanymi biletami. Nie do końca wiem jednak jak połączyć te tabele w taki sposób aby powyższy problem został uwzględniony.

Pozdrawiam wszystkich życzliwych Łukasz

0

Ten problem to problem programisty, nie projektanta baz danych.

Seans -> data
Seans -> ile miejsc

I tu masz relacje wiele do wielu, możesz jednak uprościć do 1 do wielu.

1 seans może mieć wiele dat, ma określoną ilość miejsc.
I to wystarczy tak naprawdę. Reszta to kwestia kodowania aby nie pozwolić zarezerwować więcej na SEANS, DATA niż wynosi ilość miejsc.
Tyle, że ilości miejsc nie ograniczasz w tabeli bazy danych. To ograniczenie z założeń programu, zwykle zmienne. A może być i stałe przyjmujące, że MAX = wielkość_sali_kinowej.

0

@youmound jednak warto by było mieć zabezpieczenie na bazie danych aby nie dało się sprzedać dwa razy tego samego miejsca. Ja osobiście takie rzeczy lubię zabezpieczać również po stronie bazy. Więc tu jak najbardziej jest miejsce dla projektanta baz danych.

Zawsze można zrobić tabelę w której będą rekordy w stylu (z racji, że nie będziesz przecież miał tabeli z 100 kolumn oznaczających, że dane miejsce sprzedane zostało):
ID, SeansId, MiejsceNr, (pozostałe dane np. nabywcy biletu)

Potem nakładamy klucz unikalnego złożony z dwóch pól SeansId oraz MiejsceNr
Przy czym SeansId powiedzmy odnosi się do innej tabeli w której są zawarte harmonogramy wyświetlania filmów. Takie dane jak film, data z godziną i co tam jeszcze potrzeba.

0

@Mr.YaHooo: Dziękuję dla obu Panom. Teraz jeszcze muszę tylko znaleźć jak się takie złożone klucze robi :)

0

Cóż, jeśli nie masz narzędzia aby to wyklikać sobie (ewentualnie chcesz to zrobić z palca) zrób to w ten sposób https://stackoverflow.com/questions/635937/how-do-i-specify-unique-constraint-for-multiple-columns-in-mysql

0

Dla każdego seansu wygeneruj bilet dla każdego miejsca. Następnie dodaj cechę, czy bilet sprzedany czy nie.

Na przykład:

Table ticket_for_show
spot_number,
show_id,
price_netto,
price_brutto,
is_sold (true/false)

Table hall
id,
name,
number_of_spots

Table show
id,
hall_id,
show_date_time

Wydaje mi się że nazwy pól i struktura są samo wyjaśniające się.

W momencie dodania do tabeli show rekordu - czyli stworzenia nowego seansu, powinny się wygenerować rekordy w tabeli "ticket_for_show" - dla każdego miejsca w hall powiązanego z danym show.

Jeżeli w danym hall masz np. 60 miejsc, to generujesz 60 rekordów w tabeli ticked_for_show gdzie spot spot_number jest od 1 do 60.

Klucz unikalny / primary key dla "ticket_for_show" powinien składać się z kolumn "spot_number" + "show_id"

Lubię modelować bazy danych, mógłbym mieć pracę gdzie tylko i wyłącznie to bym robił... ehhhh

1
TomRZ napisał(a):

Dla każdego seansu wygeneruj bilet dla każdego miejsca. Następnie dodaj cechę, czy bilet sprzedany czy nie.

Za takie pomysły powinni od razu zabierać "licencję programisty"

0

Do tych panów burzących się o generowanie biletów: nie trzeba generować, można traktować wpis do ticket_for_show jako sprzedaż biletu, obydwa rozwiązania mają swoje zalety i wady.

Przy okazji przypominam, że to nie 1985 rok, kiedy liczyło się każdy bajt. Jeden bilet to kilka - kilkanaście bajtów danych, przy średniej wielkości kinie mamy przyrost kilkunastu - kilkudziesięciu kb dziennie, ogarnijcie się trochę zanim wściekle się na kogoś rzucicie.

1

to ty się ogarnij - to jest NAJGŁUPSZE rozwiązanie, które prędzej czy później ugryzie w dupę. Wcale nie chodzi o zajęte miejsce czy ilość rekordów w tabeli - chodzi o logikę tego rozwiązania.

1

No dobrze to wymaga wyjaśnienia, nie dla trolli pokroju "abrakadaber" ale dla innych ludzi.

Mając system np. do zakupu biletów na samolot, gdzie mamy miejsca podobnie jak w kinie, jest pewien problem: niedopuszczenie do zakupu tego samego miejsca przez dwie różne osoby.

Mając system gdzie pre-generujemy malutkie rekordy dla każdego miejsca, niedopuszczenie do tej sytuacji jest bardzo proste i komfortowe: po prostu pobieramy slot miejsca/bilet z klauzulą "FOR UPDATE", jeżeli ma status wolnego, dokonujemy zakupu, zmieniamy status i zwalniamy blokadę.

Tymczasem bez pre-generowania, zapewnienie, że nie będzie zakupu tego samego miejsca równocześnie jest trudniejsze.

Można zrobić tak jak proponuje Marcin Miga, czyli klucz/indeks unikalny, ale wtedy:

  • po pierwsze mamy dodatkowy/większy indeks
  • po drugie jego naruszenie w przypadku konfliktu generuje błąd, takich sytuacji powinno się unikać

Należy też pamiętać, że przy tego typu systemach często robi się systemy archiwalne, czyli dane starsze niż X czasu lądują w osobnej archiwalnej bazie, baza produkcyjna nigdy nie jest duża, więc pre-generowanie nie jest żadnym problemem.

To tak w skrócie, bo temat można rozwijać bardziej, ale w tym momencie nie mam czasu.

Aha i pomyślcie też co się dzieje kiedy ktoś anuluje zakup - mamy sytuację zmiana statusu istniejącego slota vs skasowanie wpisu, co jest lepsze - do przemyślenia, tutaj znowu pre-generowany slot pokazuje wyższość.

Jak to się ma do określenia że to "NAJGŁUPSZE" rozwiązanie? Oceńcie sami.

1
  1. przy cyklicznych wydarzeniach (a lot czy seans w kinie w większości przypadków taki jest) generujesz od razu wszystkie "rekordziki" czy jak?
  2. jeśli index jest większy od "rekordziku" (chyba nie powiesz mi, że na tej tabeli nie masz indeksu i update leci po całej tabeli, żeby znaleźć rekord) to chyba coś tu nie działa
  3. insert jest zawsze szybszy od update (część baz nie robi in place update tylko oznacza rekord jako usunięty i wstawia nowy) bo nie musi szukać rekordu do update
  4. co jeśli zostało jedno miejsce a kilka osób chce je kupić w tym samym czasie? Wszyscy poza pierwszą dostaną info, że już go nie ma a potem ta pierwsza osoba zrezygnuje, co jeśli ktoś zaczął kupować miejsce i poszedł na obiad a potem się rozmyślił? - znowu miejsce zablokowane na dłuższy czas
  5. rzuceniem wyjątkiem przez bazę vs odpytanie bazy o konkretny rekord no ja nie wiem co jest szybsze/lepsze. BTW próba zakupu tego samego miejsca to jest błąd i tak powinien być traktowany
    Generalnie można pominąć wszelkie rozważania co jest szybsze (bo dla usera różnica nawer rzędu 1s nie ma znaczenia) i zajmuje więcej miejsca na dysku (bo to nie problem).

Podstawowym problemem z "malutkimi" rekordami jest to, że to nie baza pilnuje spójności danych! Jak się coś gdzieś zrypie to już nie będzie tak fajnie - jak jest index unikalny to on jest unikalny i koniec.
BTW co to są te "malutkie rekordy" i czym one się różnią od rekordów po prostu dodawanych w momencie, kiedy rezerwacja/zakup się pojawia? Czy wtedy są dodawane nowe rekordy z takimi danymi jak np. kto miejsce zakupił? A co w razie anulowania - te dodatkowe zostają czy jak to działa?

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