Baza danych i transakcje

Baza danych i transakcje
KI
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 5 lat
  • Postów:64
0

Cześć.

Pracuję nad projektem aplikacji ankiet uczelnianych. Opracowałem schemat bazy danych. Niestety nie mogę sobie poradzić z transakcjami do procedur i funkcji.

Bardzo proszę o pomoc w utworzeniu poziomów izolacji transakcji i informację dlatego tak a nie inaczej. Wszędzie wydaje mi się sensowne jedynie read commited :/

OPIS TABEL:
ankiety_wypelnione - przechuje informacje o tym, kto wypełnił ankietę ( później nie może już jej wyświetlić )
historia - zapisuje informacje o zmianach ( w nazwach ankiety, treści pytania )
pytania - przechowuje pytania przypisane do ankiet
pytania_typy - przechowuje informacje o typach pytań ( taknie, ocena, tekstowa itp; w każdej chwili można dodać nowe typy )
odpowiedzi - tabela odpowiedzi do pytań ( anonimowe, nie można wiedzieć jaki użytkownik udzielił daną odpowiedź )
odpowiedzi_archiwum - tabelka archiwalna wypełniana co określony czas za pomocą eventu
ankiety - przechowuje informacje o utworzonych ankietach ( nazwa, data otwarcia, data zamknięcia, informacja o tym do jakiego przedmiotu ją przypisujemy )
uzytkownicy - tabelka do zalogowania, konta użytkowników ( wspólna dla studentów, pracowników, administratorów itd )
uzytkownicy_typy - typy użytkowników ( np: student, wykładowca, administrator itd; w kazdej chwili można dodać nowe typy )
prowadzacy - tabela przypisuje użytkowników ( wykładowców ) do przedmiotów na danych wydziałach i kierunkach ( prowadzący może prowadzić wiele przedmiotów na różnych wydziałach, przedmioty mogą mieć wielu prowadzących )
studenci_przedmioty - przypisujemy studentów do przedmiotów na danych kierunkach ( po to aby móc wyświetlić im stosowne ankiety )
kierunki_przedmioty - tabelka złączeniowa przypisująca przedmioty do kierunków
przedmioty - tabela przechowuje przedmioty
kierunki - tabela kierunków ( są przypisane do wydziałów )
wydziały - tabela wydziałów

OPIS PROCEDUR I FUNKCJI:
archiwizuj_odpowiedzi - procedura wywoływana raz w roku co event, przenosi stare odpowiedzi do archiwum
dodaj_studenta - procedura dodawania nowego studenta
ile_uprawnionych - funkcja zwracająca liczbę uprawnionych do wypełnienia ankiety
ile_wypełniło - funkcja zwraca liczbę osób, które wypełniło ankietę
odpowiedz - procedura odpowiedzi na dane pytanie
srednia_pytania - funkcja zwraca średnią liczbę oceń dla pytań typu "ocena"
zaktualizuj_pytanie - funkcja umożliwiająca aktualizację treść pytania, jeśli nikt jeszcze nie udzielił na nie odpowiedzi

user image

Kopiuj
CREATE PROCEDURE `archiwizuj_odpowiedzi`()
BEGIN
	set session transaction isolation level read committed;

	insert into odpowiedzi_archiwum select * from odpowiedzi where odpowiedzi_data < DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
	delete from odpowiedzi where odpowiedzi_data < DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
	
	commit;
END


CREATE PROCEDURE `dodaj_studenta`(`login` varchar(50),`haslo` varchar(50),`email` varchar(50),`imie` varchar(50),`nazwisko` varchar(80),`typ` varchar(30))
BEGIN
	DECLARE TYPY_ID INTEGER;
	DECLARE USER_COUNT INTEGER;
	set session transaction isolation level read uncommitted;

	SELECT uzytkownicytypy_id INTO TYPY_ID FROM uzytkownicy_typy WHERE uzytkownicytypy_nazwa = typ;
	
	SELECT COUNT(*) INTO USER_COUNT FROM uzytkownicy WHERE uzytkownicy_login = login OR uzytkownicy_email = email;

	IF TYPY_ID > 0 AND USER_COUNT = 0 THEN
		INSERT INTO uzytkownicy(uzytkownicy_id,uzytkownicy_login,uzytkownicy_haslo,uzytkownicy_email,uzytkownicy_imie,uzytkownicy_nazwisko,uzytkownicytypy_id) VALUES(null,login,haslo,email,imie,nazwisko,TYPY_ID);
	END IF;

	commit;
END


CREATE FUNCTION `ile_uprawnionych`(`ankieta` int) RETURNS int(11)
BEGIN
	declare studenci int;
	declare kierunek int;
	declare kierunkiprzedmioty int;
	
	select kierunkiprzedmioty_id into kierunkiprzedmioty from ankiety where ankiety_id = ankieta;
	select count(studenciprzedmioty_id) into studenci from studenci_przedmioty where kierunkiprzedmioty_id = kierunkiprzedmioty;

	RETURN studenci;
END



CREATE FUNCTION `ile_wypelnilo`(`ankieta` int) RETURNS int(11)
BEGIN
	declare liczba int;
	select count(*) into liczba from ankiety_wypelnione where ankiety_id = ankieta;

	RETURN liczba;
END




CREATE PROCEDURE `odpowiedz`(`pytanie` int, `odpowiedz` varchar(500))
BEGIN
	declare ocena int;
	declare typ int;
	declare odp varchar(500);
	set odp = cast(odpowiedz as unsigned);
	set session transaction isolation level read committed;

	select pytaniatypy_id into ocena from pytania_typy where pytaniatypy_nazwa = 'ocena';
	select pytaniatypy_id into typ from pytania where pytania_id = pytanie;
	if pytanie > 0 then
		if typ = ocena then
			if odp > 0 then
				insert into odpowiedzi (odpowiedzi_id,pytania_id,odpowiedzi_tresc,odpowiedzi_data) VALUES(null,pytanie,odpowiedz,NOW());
			end if;
		else
			insert into odpowiedzi (odpowiedzi_id,pytania_id,odpowiedzi_tresc,odpowiedzi_data) VALUES(null,pytanie,odpowiedz,NOW());
		end if;
	end if;

	commit;
END



CREATE FUNCTION `srednia_pytania`(`pytania` int) RETURNS int(11)
BEGIN
	declare liczba int;
	select avg(odpowiedzi.odpowiedzi_tresc) into liczba from odpowiedzi, pytania where pytania.pytaniatypy_id = 2 and odpowiedzi.pytania_id = pytania;

	return liczba; 
END



CREATE PROCEDURE `zaktualizuj_pytanie`(`pytanie` int,`tresc` varchar(255))
BEGIN
	
	declare lo integer;

	set session transaction isolation level read committed;	

	SELECT count(*) INTO lo FROM odpowiedzi WHERE pytania_id = pytanie;
	if lo = 0  then 
		UPDATE pytania SET pytania_tresc = tresc WHERE pytania_id = pytanie;
	end if;

	commit;
END

woolfik
  • Rejestracja:ponad 17 lat
  • Ostatnio:około 20 godzin
  • Postów:1595
0

Specem od MySQL nie jestem ale podpowiem Ci co nie co bazując na oracle. Po pierwsze do czego się doczepię to funkcje jak np ile_uprawnionych w zasadzie jeśli potrzebujesz tylko count to możesz zrobić widok w przypadku Oracle (i MySQL pewnie też) przy bardzo dużych zbiorach danych baza ma problem przy przechodzeniu między SQL i PL/SQL i takie funkcje nie są zbyt wydajne proponuję zatem przenieść to na VIEW.
Druga rzecz to widzę, że archiwizujesz ankiety i odpowiedzi ale pytań już nie ... co Ci da odpowiedź w archiwum jeśli nie wiesz jak brzmiało pytanie?
Teraz co do tych Twoich transakcji. Nie wiem jak będzie wyglądał interfejs użytkownika ale jak znam życie to będzie pewnie jakiś formularz HTML. Jeśli tak to w przypadku archiwizuj_odpowiedzi w Oracle użyłbym kursora

Kopiuj
for rec in (select * from odpowiedzi where ... for update nowait) loop
  insert i delete
end loop;
commit;

takie rozwiązanie może jest i nieco mniej wydajne ale przynajmniej przyblokujesz rekordy przeznaczone do usunięcia i zachowasz pewność, że nikt ich w międzyczasie nie zmieni.
Co do dodaj_studenta to tutaj możesz zostawić tak jak teraz jest lub nawet użyć autonomicznej transakcji (jeśli masz taką potrzebę) ale wątpię.
Problem pojawia się w odpowiedz bo jak rozumiem pytań będzie X, dla każdego pytania ma być odpowiedź i to pewnie jeszcze z możliwością cofnij, popraw itp. w takim wypadku jak bym to przerobił w taki sposób aby po stronie interfejsu użytkownika przechowywać całość odpowiedzi i dopiero w momencie zatwierdzenia ankiety przesłać całą paczkę danych w jednej transakcji. Ma to swoje + i - (za długo by tu pisać) ale uważam, że w Twoim przypadku będzie to najbezpieczniejsze rozwiązanie.

KI
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 5 lat
  • Postów:64
0

Dzięki za odpowiedź. Jak dobrze zauważyłeś - brak dwóch tabel archiwizujących oraz zbędne funkcje.
System ten jest pisany póki co na zaliczenie przedmiotu i prowadzący zgodził się aby na potrzeby zaliczenia zrobić tylko jedną tabelę ( żeby pokazać że umie się eventy, triggery ). Podobnie z funkcjami - są tutaj tylko na pokaz.

W przyszłym semestrze będę pisał do tego aplikację i na pewno te funkcje i procedury pozmieniam.

Co do tego co napisałeś - niestety nie rozumiem odniesienia do MySQL.
Czy ktoś jeszcze potrafi pomóc ?

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)