Wątek zablokowany 2011-01-23 11:31 przez Adam Boduch.

MySQL, INSERT INTO... i FOREIGN KEY

0

Mam dwie tabele wychowawce i klasę:


CREATE TABLE IF NOT EXISTS `uzytkownicy` (
  `id_uzytkownicy` int(2) NOT NULL AUTO_INCREMENT,
  `imie` char(30) CHARACTER SET utf8 COLLATE utf8_polish_ci NOT NULL,
  `nazwisko` char(30) CHARACTER SET utf8 COLLATE utf8_polish_ci NOT NULL,
  `login` char(12) CHARACTER SET utf8 COLLATE utf8_polish_ci NOT NULL,
  `haslo` char(50) CHARACTER SET utf8 COLLATE utf8_polish_ci NOT NULL,
  `ranga` int(1) NOT NULL,
  `email` char(20) CHARACTER SET utf8 COLLATE utf8_polish_ci NOT NULL,
  PRIMARY KEY (`id_uzytkownicy`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=342 ;
CREATE TABLE IF NOT EXISTS `klasy` (
  `id_klasy` int(2) DEFAULT NULL AUTO_INCREMENT,
  `id_uzytkownicy` int(2) DEFAULT NULL,
  `klasa` int(2) NOT NULL,
  `literka` enum('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','w','x','y','z') DEFAULT NULL,
  PRIMARY KEY (`id_klasy`),
  FOREIGN KEY (`id_uzytkownicy`) REFERENCES uzytkownicy(`id_uzytkownicy`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=58 ;

i mam problem z relacją, czyli nie wiem jak połączyć wychowawcę z klasą ?? Jak dany wychowawca zaloguję, żeby miał wgląd tylko do swojej klasy i żadnej innej. I jak zapisać dane insertem? mam najpierw dodać wychowawcę później klasę? czy za raz wszystko? w jednym formularzu?

Przykładowo jak zrobie tak nie działa? wiec jak to powiązać? z tych dwóch zapytań zrobić jedno?


INSERT INTO `uzytkownicy` (`id_uzytkownicy`, `imie`, `nazwisko`, `login`, `haslo`, `ranga`, `email`) VALUES
(22, '', '', 'admin', 'admin', 1, '');

INSERT INTO `klasy` (`id_klasy`, `id_uzytkownicy`, `klasa`, `literka`) VALUES
(1, 1, 2, 'd');
0

Do uzytkownikow pewnie nie możesz dodać, bo podajesz Null imie i nazwisko, a oba te pola są NOT NULL bez defaulta.
Co do klas zaś, to podajesz id_szkoly (którego nie widzę), a nie podajesz id_uzytkownicy.
I powinno być w tej kolejności. Najlepiej w transakcji.

0

Rozumiem, ale chcę połączyć wychowawcę z klasą to jak inaczej to zrobić?

Zrobiłem takie zapytanie:
W zapytaniu przez login i hasło wychowawcy chcę wyszukać jakiej klasy jest wychowawcą.

$sql = "SELECT u.login, u.haslo,\n"
    . " k.klasa, k.literka\n"
    . "FROM uzytkownicy u\n"
    . "LEFT JOIN klasy k ON u.id_uzytkownicy = k.id_uzytkownicy LIMIT 1";

Czy takie może być, czy jest za banalne ?

Dalej nie mam pojęcia jak zrobić inserta do tych dwóch tabel? mam zrobić jeden formularz ? i dodać klase i od razu wychowawce? czy pierwszo wychowawcę, a poźniej przez userID tego wychowawcy, dodam to do tab. klasa i wtedy dodaje już całą klasę?

0

Tworzysz jeszcze jedna tabele (np. wychowawcy) w ktorej laczysz ID uzytkownika i ID klasy.

0

a jak zapisać do takiej tabeli wychowawcy wychowawcyID i klasyID? pierwszo pobrać selectem z dwóch tabel ID a poźniej zapisać je w tej tabeli ? A może pobrać ID uzytwkonika juz wczasie logowania, zapisać do sesji itd?

0

Hmm... nie rozumiem. Jezeli dodajesz jakas klase, to uzyskujesz ID nowo dodanego rekordu. Majac ID klasy i ID usera (wychowawce) dodajesz nowy rekord do tabeli wychowawcy. Generalnie nie wiem na czym polega problem.

A majac te dane mozesz pobrac informacje o klasie i o wychowawcy w ten sposob:

SELECT klasy.*, uzytkownicy.*
FROM klasy
INNER JOIN wychowawcy ON wychowawcy_klasa = id_klasy
INNER JOIN uzytkownicy ON id_uzytkownicy = wychowawcy_uzytkownik

Zakladajac, ze tabela wychowawcy bedzie wygladala tak:

Kolumna Opis
wychowawcy_klasa ID klasy
wychowawcy_uzytkownik ID uzytkownika z tabeli uzytkownicy
0

Rozumiem i dziękuję za podpowiedz, przyda się na pewno :)

Mam jeszcze jeden problem. Nie wiem jak mam dodać wychowawcę i klasę (dane do odpowiednich tabel), żeby w tabeli klasy w wierszu uzytkownicyID automatycznie znalazł się ID odpowiedniego uzytkownika? Chodzi mi tu o samo działanie referencji w tabeli klasy? Ja to rozumiem tak:

  1. Na samym początku dodaje tylko wychowawce do tabeli uzytkownicy (i uzyskuje jego ID np 45)
    2.Pobieram i zapisuję do zmiennej (w php) $id = 45;
    3.I teraz dodaję klasę, np 3 C i tu w tym INSERCIE do bazy dodaje od razy uzytkownikID($id = 45).
    I dzięki temu mam referecncje w tabeli klasy.

Czy takie obejście problemu jest dobre? Robię to pierwszy raz i nie jestem pewny czy dobrze podchodzę do sprawy :/
Chodzi mi o samą istotę uzytkownikID w Tabeli klasy, jak wartość tego wiersza ma się tam pojawić, jak i kiedy zapisać te ID usera do Tabeli klasy bo automatycznie to nie zrobi się jak dodam samego użytkownika...

Mile widziane komentarze :)

0

Ale z tabeli uzytkownicy wywalasz kolumne uzytkownikID. Nie potrzebujesz juz jej poniewaz masz do tego osobna tabele -- wychowawcy. A kroki postepowania:

  1. Dodajesz nowego uzytkownika (wychowace)
  2. Dodajesz nowa klase do tabeli klasy
  3. Dodajesz nowy rekord do tabeli wychowawcy poniewaz na tym etapie masz ID klasy i ID uzytkownika
0

nie do końca rozumiem... :( Przydałby się przykład w kodzie... php. i nie rozumiem etapu 3, ponieważ jeśli wyrzucam z tabeli uzytkownicy kolimne IDuzytkownika to skąd mam mieć IDuzytkownica w tabeli wychowawcy ?

0
$result = mysql_query('INSERT INTO uzytkownik (nazwisko) VALUES("Jan Kowalski")'); // Jan Kowalski bedzie wychowawca, ok?
$idUzytkownik = mysql_insert_id($result);

$result = mysql_query('INSERT INTO klasa (nazwa,opis) VALUES("Klasa 3B", "Opis klasy")');
$idKlasy = mysql_insert_id($result);

// mamy ID Klasy i ID uzytkownika
mysql_query('INSERT INTO wychowawcy (id_wychowawcy, id_klasy) VALUES(' . $idUzytkownik . ', ' . $idKlasy . ')');

Nie traktuj tego kodu zbyt doslownie, poniewaz uproscilem go, aby pokazac jedynie zarys koncepcji :)

0

Teraz kumam wszystko. Dziękuję bardzo za pomoc i cierpliwość :)
Tej linijki mi brakowało:

 $idKlasy = mysql_insert_id($result); 

do szczęścia.

0

witam ponownie,
mam mały problem z kluczem obcym :( nie wiem czy do tej tabeli wychowawcy mam dodać do tych dwóch wartości klucze obce? czy nie są potrzebne? Bo jak będę np łączył dwie tabele select... left join... to czy wymagane jest przy takim zapytaniu, żeby w którejś z tabel był klucz obcy. Czy klucz obcy nie jest potrzebny do łączenia dwóch tabel (wydaje mi się to zbędne) czy dobrze sądzę? Nie rozumiem po co jest ten klucz obcy, ogólnej idei nie mogę pojąć :( I pytanie do transakcji, stosuję taki kod, ale nie działa :(

mysql_query('set autocommit=0');
mysql_query('start transaction');

$sql=insert into...
$sql1=insert into...
$sql2=insert into...

mysql_query('commit');

if ($sql && $sql1&& $sql2){
echo 'ok';
}
else{
 mysql_query('rollback');
}

co może być nie tak? jutro przerobie to jeszcze na interfejs z POD, może zadziała :( ?

0

Klucz obcy nie jest potrzebny do zapytania SELECT. Nie jest on w ogole wymagany do niczego.
Ale pomocny w przypadku usuwania, aktualizacji danych. Np. usuwajac rekord z tabeli uzytkownik, baza danych sama zadba o to, aby usunac zbedne juz rekordy z tabeli powiazanej => wychowawcy.

Transakcje i klucze obce dzialaja w MySQL w tabelach typu InnoDB - NIE MyISAM

Co do transakcji: cofniecie transakcji powinno wystapic w przypadku bledu, prawda?

$connection = mysql_connect('localhost', 'root', 'root', 'baza');

try
{
	mysql_query('BEGIN', $connection);

	$query = mysql_query('SELECT * FROM...', $connection);
	if (!$query)
	{
		throw new Exception(mysql_error($connection));
	}

	mysql_query('COMMIT', $connection);
}
catch (Exception $e)
{
	mysql_query('ROLLBACK', $connection);
	echo $e->getMessage();
}

P.S. Nie musisz od razu uzywac PDO. Mozesz jednak zaczac uzywac biblioteki mysqli zamiast mysql. Jest to po prostu jej nowoczesniejszy odpowiednik. Dziala tak samo, z tym, ze nazwy funkcji posiadaja litere "i" - np. mysqli_query(), mysqli_error().

0

Hallo!

A.

Adam Boduch napisał(a)

Ale z tabeli uzytkownicy wywalasz kolumne uzytkownikID. Nie potrzebujesz juz jej poniewaz masz do tego osobna tabele -- wychowawcy. A kroki postepowania:

  1. Dodajesz nowego uzytkownika (wychowace)
  2. Dodajesz nowa klase do tabeli klasy
  3. Dodajesz nowy rekord do tabeli wychowawcy poniewaz na tym etapie masz ID klasy i ID uzytkownika

Nie rozumiem stwiedzenia, ze z tabeli uzytkownicy powinna byc usunieta kolumna uzytkownikID.

Nie jest to bardzo odkrywcze :-) ale, tabele "uzytkownik" i "wychowawcy" musza byc w jakis sposob se soba powiazane. Innymi slowy: musi istniec miedzy nimi pewna relacja. Taka relacje tworzy kolumna "uzytkownikID", ktore jest kluczem w tabeli "uzytkownik" i kluczem obcym w tabeli "wychowawcy". Jezeli teraz z tablicy uzytkownicy usuniemy kolumne uzytkownikID, to w jaki sposob uzyskac dane z tabeli "uzytkownik" majac do dyspozycji "id-wychowawcy" z tabeli "wychowawcy" jezeli kolumna "uzytkownikID" nie bedzie w tabeli "uzytkownik" istniala?

Czy moze pierwsze zdanie powinno brzmiec: "Kolumna uzytkownikID powinna byc w tabeli uzytkownicy zastapiona kolumna "ID" i taka sama kolumna "ID" powinna byc zdefiniowana w tabeli "wychowawcy""?

B.

Adam Boduch napisał(a)

Klucz obcy nie jest potrzebny do zapytania SELECT. Nie jest on w ogole wymagany do niczego.
Ale pomocny w przypadku usuwania, aktualizacji danych. Np. usuwajac rekord z tabeli uzytkownik, baza danych sama zadba o to, aby usunac zbedne juz rekordy z tabeli powiazanej => wychowawcy.

...

Jako newbie nie rozumiem stwierdzenia, ze klucz obcy "nie jest w ogole do niczego potrzebny", ale tylko "pomocny". Sugeruje to, ze klucza obcego moznaby bylo w ogole nie uzywac. W jaki sposob wiec zapewnic relacje miedzy tabelami (relacjonalny model bazy danych)?

Prosze o wyjasnienie.

Pozdrawiam
Markus

0

ja dołączam podobnie jak użytkownik MarkusB prośbę o wyjaśnienie. Od niedawna zajmuję się MySQL i mam kilka wątpliwości bo ja zrobiłbym tak, że zostawiłbym w obu tabelach iduzytkownika(wtabeli uzytkowniyc) i idklasy(w tabeli klasy) te dwie wartości dałbym na klucz główny. I teraz mogę tworzyć klucz tabelę wychowawcy, gdzie są twie kolumnu. Iduzytkownika i Idklasy i te dwie wartości daje na klucze obce :) Tak wydaje mi sie rozsądnie :) bo zakładam, że będę mógł zrobić aktualizację, usunąć rekord itd, poza tym piszę projekt na zaliczenie w szkole i wydaje mi się, że muszę użyć relacji. Tylko mam problem... bo nie wiem jak to jest, ale mam jeden formularz: w nim, dodaję na początku klasę do niej wychowawce, zapisuje mi to w bazie do dwóch tabel dane. ale mam problem z zapisaniem ID w tabeli trzeciej (wychowawcy). jak mam relacje nie mogę zapisać :( usunę klucze obce(relacje) i zapisuje. ale potrzebuję tych relacji i szukałem, czytałem, znalazłem coś o transakcji, wcześniej też ktoś napisał na forum o tym, dziś przerobie to na mysqli tak jak zostało tu opisane PDO na razie zostawie :) może się uda, ale nie wiem jak to jest ze mam klucze obce i juz nie jest błąd w zapisaniu do bazy :( coś jest nie tak...

0

Hallo poniatowski!

Moim zdaniem, nie musisz nic zmieniac w konstrukcji tabel.

poniatowski napisał(a)

i mam problem z relacją, czyli nie wiem jak połączyć wychowawcę z klasą ??

Dlaczego musisz laczyc nauczyciela z klasa? Przeciez poprzez relacje

FOREIGN KEY (`id_uzytkownicy`) REFERENCES uzytkownicy(`id_uzytkownicy`)

masz palaczona klase z nauczycielem. Czy to nie wystarczy?

poniatowski napisał(a)

Jak dany wychowawca zaloguję, żeby miał wgląd tylko do swojej klasy i żadnej innej.

Kazdy nauczyciel ma swoje jednoznaczne "id_uzytkownicy", ktore jest znane od momentu zalogowania. Nalezy wykozystac ta informacje do filtrowania danych z tabeli "klasy". Na przyklad za pomoca query w ktorym definiujesz klausule "where" w ten sposob:

select * from klasy
where id_uzytkownicy = wartosc "id_uzytkownicy" zalogowanego nauczyciela

W ten sposob kazdy zalogowany nauczyciel bedzie widzial dane tylko z tej klasy (z tych klas) gdzie jest wychowawca.

poniatowski napisał(a)

I jak zapisać dane insertem? mam najpierw dodać wychowawcę później klasę? czy za raz wszystko?

Z definicji relacji wynika, ze:

  • nowego nauczyciela mozna dopisywac do tabeli "uzytkownicy" zawsze (nie ma tu zadnych ograniczen)
  • nowa klase mozna dopisywac do tabeli "klasy" tylko wtedy kiedy "id_uzytkownicy" z aktualnie dopisywanej klasy istnieje juz w tabeli "uzytkownicy" (to wymusza relacja)

Czyli aby dopisac nowa klase najpierw muisz miec zdefiniowanego nauczyciela.

poniatowski napisał(a)

w jednym formularzu?

Obojetne, jak chcesz (ale musi byc zachowana wyzej opisana kolejnosc).

Pozdrawiam i zycze wszystkiego najlepszego w Nowym Roku
Markus

0

a jak do tego wszystkiego dodać teraz uczniów?

0

Uczniów? Tabela uczniowie, w niej id_ucznia, imię, nazwisko, id_klasy.
Jedno mnie nurtuje - co to są za kolumny "klasa" i "literka" w tabeli klasy? Czemu tak?

0

to są oznaczenia, skrót, identyfikator klasy. Np 1A, 2B, 3C etc. klasa czyli liczby i literka porządkowa. Myślę, że tak jest spoko, ale jak ma ktoś lepszy pomysł jestem otwarty na wszelkie sugestie. Czy mam to połączyć w jedną kolumnę ?

0

Ja kończyłem liceum będąc w klasie 4LB, więc do Twojej tabeli nie można by mnie dopisać. Ja bym zrobił po prostu jedną kolumnę typu znakowego.

0

ok, wcześniej nie miałem czasu z tym projektem bo miałem coś innego do roboty :( ale do piątku chcę zrobić bazę, formularze i wszystko związane z tym etc. Będzie musztra :)

Mam teraz problem z zapytaniami do tych tabel:
Jak dodam juz wychowawcę i klasę, co robi dyrektor szkoły, nie wiem jak zrobić zapytanie jak zaloguje sie dany wychowawca, żeby wyświetlało tylko klasę którą uczy np 1A, mój kod:

gdzie $id_uzytkownicy jest to wczytywana zmienna sesyjna juz przy logowaniu. pobieram po prostu id logujacego sie wychowawcy i zapisuje do sesji.

$sql = "SELECT u.*,\n"
    . " k.*\n"
    . "FROM uzytkownicy u\n"
    . "LEFT JOIN klasy k ON $id_uzytkownicy = k.ID_uzytkownicy LIMIT 1";

Ten kod wyświetla wszystkich klasy :(

0

SELECT k.* FROM klasy k JOIN wychowawcy w ON k.id_klasy=w.id_klasy WHERE w.id_wychowawcy=$id_uzytkownicy

0

dzięki, zrobiłem podobnie i już działa :)

0

wsio gra ;)

0

Mam jeszcze jeden, problem. Z tablą oceny.

Ma ktoś może pomysł jak napisać do tego wszystkiego wyświetlanie ocen dla danego ucznia?

Mam z tym problem, reszta już działa, dodaje ucznia, wychowawce, przedmioty, klasy wszystko, ale teraz mam wielkiego zgryza jak napisać skrypt wyświetlający dany przedmiot, listę uczniów i oceny do odpowiedniego ucznia?

0

Nie rozumiem tego pytania. Tabela oceny powinna zawierac ID przedmiotu, ID ucznia i date wystawienia. No - moze jeszcze ID nauczyciela. W czym tkwi problem?

0

Uuu przepraszam, mój błąd. Źle sprecyzowałem pytania. Chodzi mi o to jak mam już przedmiot, listę uczniów i oceny do odpowiednich uczniów jak teraz zrobić "dziennik" tzn formularz, gdzie będę miał np na górze nazwę przedmiotu, po lewej listę uczniów i na środku oceny. Wiadomo jak, kartka z dziennika. Na razie zrobiłem wyświetlenie Uczniów po lewej, ale wstawienie ocen? koszmarrrr... Wstawiłem id_ucznia + numerek dla każdego pola formularza, mój kod:

 <FORM  METHOD=POST ACTION="">
	<TABLE">

	<tr>
		<td>uczeń</td>
		
		<td colspan="10">oceny cząstkowe</td>  
		
		<td>ocena semestralna</td>
	</tr>
	
{foreach item=uczniowie1 from=$uczen}		//pętla ze smartów, z listą uczniów, z imieniem i nazwiskiem
		<TR>
			<TD><B>{$uczniowie1.imie} {$uczniowie1.nazwisko} </B> </TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k1" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k2" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k3" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k4" size="1" VALUE=""> 
			</TD> 
			

			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k5" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k6" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k7" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k8" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k9" size="1" VALUE=""> 
			</TD> 
			
			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k10" size="1" VALUE=""> 
			</TD> 

			<TD>
				<INPUT TYPE="text" NAME="{$uczniowie1.id_uzytkownicy}w1_k12" size="1" VALUE=""> 
			</TD> 			
		</tr>
{/foreach} 	
	
</TABLE>
	<INPUT TYPE="submit" NAME="submit" VALUE="zapisz oceny">
	<INPUT TYPE="reset" value="wyczyść oceny">

	</FORM> 

Ale jak napisać teraz kod w PHP. Toż to ile zapytań do bazy, do tabeli oceny? jak to zrobić?

0

Usunalem Twojego posta, gdyz podbijanie tematu nic nie da. Jezeli ktos bedzie chcial, to odpowie. Wstawienie wielu rekordow do jednej tabeli mozna zrealizowac jednym zapytaniem:

INSERT INTO foo(id, value) VALUES(1,'test'),(2,'test2'),(3,'test3');
0

Mam takie pytanie,też na temat kluczy obcych.
Stworzyłam dwie tabele

create table POMIARY_GLOWNA(
       -> ID_PUNKTU integer ,
       -> NR_PUNKTU integer PRIMARY KEY,
       -> PRACOWNIK varchar(20),
       -> ODLEGLOSC integer,
       -> DZIEN varchar(20));

 create table POMIARY_MIEJSCOWOSC(
    -> NR_PKT integer ,
    -> MIEJSCOWOSC varchar(20) PRIMARY KEY,
    -> WSPOLRZEDNA_X float,
    -> WSPOLRZEDNA_Y float);

Chciała ustawić klucz obcy na NR_PKT
Zrobiłam takie coś:

ALTER TABLE POMIARY_MIEJSCOWOSC ADD INDEX(NR_PKT);

ALTER TABLE POMIARY_MIEJSCOWOSC
ADD CONSTRAINT PUNKT
FOREIGN KEY(NR_PKT)
REFERENCES POMIARY_GLOWNA(NR_PUNKTU)
ON DELETE CASCADE;

I nie działa. Z jednej tabeli POMIERY_GLOWNA usunę wiersze,ale nie usuwa mi to automatycznie wiersza z drugiej. Co powinnam poprawić?

EDIT:Czy moze to być spowodowane,ze nie wstawiłam silnika InnoDB?

0

Klucze obce działają tylko na silniku InnoDB. Na MyISAM już nie :(

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