DevProTalk

DevProTalk (http://www.devprotalk.com/index.php)
-   PHP (http://www.devprotalk.com/forumdisplay.php?f=9)
-   -   Normalizovana baza podataka (http://www.devprotalk.com/showthread.php?t=10386)

slavkan 23. 09. 2011. 23:49

Normalizovana baza podataka
 
Postovanje. Vezban na jednoj normalizovanoj bazi podatka i dolazim do dela gde treba da upisem podatke u 2 tabele istovremeno. Da pojasnim, radi se kao o jednoj prodavnici racunara i imam administratora koji treba da unese proizvode i da ih razvrsta po kategorijama koji oni pripadaju pa tako imam tabelu kategorije (koja je vec puna), zatim imam tabelu proizovdi i imam tabelu kategorija_proizvodi koja se dobije zbog veze vise:vise. Administrator dakle ima formu gde unosi naziv proizvoda, birakategoriju kojoj pripada i unosi broj proizvoda. E imam problem sa ovim id-ovima koji su mi u tabelama auto_increment. E kad insertujem recimo u tabelu proizvod - insertujem naizv i stanje a id mi se ubaci samo od strane sistema za upravljanja bazama e kako sad taj isti id da insertujem i u tabelu kategorija_proizvod kad taj id nigde ne cuvam ne postoji u nekoj promenljivoj. Da li sad ovde nije pozeljno koristiti ovaj autoincrement ili praviti neku promenljivu gde cu cuvati id proizvoda ili pak nesto trece. Voleo bih kad bi neko iskusniji dao neki savet oko ovoga. Evo postavicu tabele da bude jasnije:


Tabela kategorija
Kôd:

CREATE TABLE IF NOT EXISTS `kategorija` (
  `idKategorija` int(11) NOT NULL AUTO_INCREMENT,
  `naziv_kategorije` varchar(45) NOT NULL,
  PRIMARY KEY (`idKategorija`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ;

--
-- Dumping data for table `kategorija`
--

INSERT INTO `kategorija` (`idKategorija`, `naziv_kategorije`) VALUES
(1, 'Procesor'),
(2, 'Mticna ploca'),
(3, 'Monitor'),
(4, 'Hard disk'),
(5, 'RAM'),
(6, 'Graficka karta'),
(7, 'Napajanje'),
(8, 'Tastatura'),
(9, 'Mis'),
(10, 'Opticki uredjaj');

Tabela proizvodi
Kôd:

--
-- Table structure for table `proizvod`
--

CREATE TABLE IF NOT EXISTS `proizvod` (
  `idProizvod` int(11) NOT NULL AUTO_INCREMENT,
  `naziv_proizvoda` varchar(45) DEFAULT NULL,
  `stanje` int(3) NOT NULL,
  PRIMARY KEY (`idProizvod`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `proizvod`
--

Tabela kategorija_proizvod gde imam spoljne kljuceve iz tabele proizvod i tabele kategorije
Kôd:

CREATE TABLE IF NOT EXISTS `kategorija_proizvod` (
  `Kategorija_idKategorija` int(11) NOT NULL,
  `Proizvod_idProizvod` int(11) NOT NULL,
  PRIMARY KEY (`Kategorija_idKategorija`,`Proizvod_idProizvod`),
  KEY `fk_Kategorija_has_Proizvod_Kategorija1` (`Kategorija_idKategorija`),
  KEY `fk_Kategorija_has_Proizvod_Proizvod1` (`Proizvod_idProizvod`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `kategorija_proizvod`
--


--
-- Constraints for dumped tables
--

--
-- Constraints for table `kategorija_proizvod`
--
ALTER TABLE `kategorija_proizvod`
  ADD CONSTRAINT `fk_Kategorija_has_Proizvod_Kategorija1` FOREIGN KEY (`Kategorija_idKategorija`) REFERENCES `kategorija` (`idKategorija`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  ADD CONSTRAINT `fk_Kategorija_has_Proizvod_Proizvod1` FOREIGN KEY (`Proizvod_idProizvod`) REFERENCES `proizvod` (`idProizvod`) ON DELETE NO ACTION ON UPDATE NO ACTION;


webarto 24. 09. 2011. 00:49

MySQL:
PHP kôd:

last_insert_id() 

PHP kôd:

SELECT LAST_INSERT_ID() AS id 

PHP:

PHP kôd:

mysql_insert_id() 

PHP kôd:

$id mysql_insert_id(); 

....

PHP kôd:

$query "INSERT INTO proizvodi(naziv_proizvoda,stanje) VALUES('kompujtor', 5)";
$result mysql_query($query);

$id mysql_insert_id();

$query "INSERT INTO proizvodi_kategorije(Kategorija_idKategorija,Proizvod_idProizvod) VALUES(1, $id)";
$result mysql_query($query); 


slavkan 24. 09. 2011. 00:56

WOW :D

Tenk ju maestro ;)

Jasno ko dan ! Dobro samo sto cu ja morati da u kategorija_proizvod upisem jos i idKategorija iz tabele kategorija al sad je to prava poslastica :)

webarto 24. 09. 2011. 01:26

Napisao si istovremeno, a to nije moguće, moguće je samo multiple query u MySQLi extenziji ali to nije pametno koristiti.
PHP kôd:

$query "INSERT INTO proizvodi(naziv_proizvoda,stanje) VALUES('kompujtor', 5);
INSERT INTO proizvodi_kategorije(Kategorija_idKategorija,Proizvod_idProizvod) VALUES(1, (SELECT LAST_INSERT_ID()));"
;

mysqli_multi_query($link $query); 

A kako dođeš do ovog Kategorija_idKategorija, pretpostavljam iz $_POST, ako ga vučeš iz baze možeš u istom query-u...

slavkan 24. 09. 2011. 01:43

Mozda sam se pogresno izrazio ali treba da upisem podatke i u jednu i u drugu tabelu, ali logicno je da prvo upisem proizvode (id naziv i stanje) u tabelu proizvodi pa onda da upisem (Kategorija_idKategorija,Proizvod_idProizvod) u tabelu kategorija_proizvod. Kategorije su prethodno upisane.

A kako doci do Kategorija_idKategorija, pa da sa $_POST kako bih mogao drugacije? Da li mozda postoji neko bolje i prakticnije resenje od ovoga? Dakle ja uglavnom moram da omogucim administratoru da on moze da dodaje proizvode u tabelu proizvodi i da ih rasporedjuje po kategorijama, a to ce da uzrokuje da moram da popunjavam i tabelu kategorija_proizvodi sa id-ovima od proizvoda i kategorija jer je to valjda sustina normalizacije, da izbegnem dupliranje podataka itd.

Jos jedno pitanje, zasto nije pametno koristi mysqli ? Da li ta funkcija bukvalno omogucava istovremeni upis u obe tabele? Meni to i ne treba, zar ne?

webarto 24. 09. 2011. 02:06

Ne treba ti, ako ti treba, ne radiš dobro :)
MySQLi (improved) je ekstenzija a to je samo jedna od njenih funkcija (http://php.net/manual/en/book.mysqli.php)...
Pa ne, preko POST naravno, a kako si napisao učinilo mi se kao da je neki problem :)

Jeste to normalizacija, upravo sam radio za djevojku neku Access bazu (pohađa napredni kurs za Office)...



Uglavnom, predavač je rekao da ne mora da ima ovoliko tabela i da to može sve u jednu tabelu jer je lakše, takođe može staviti PRIMARY na VIN (koji je sastoji od slova i brojeva), talking about normalization :)

slavkan 24. 09. 2011. 02:15

Ma da , necu ulaziti sad u taj mysqli :D Pokusacu sutra ovo da insertujem pa se javljam, nebi trebalo biti problema.

E gledam ovaj Access :D Jel se moze ovo danas negde iskoristiti ?

ivanhoe 24. 09. 2011. 03:49

Nema razloga da ne koristis mysqli, to je samo drugaciji (noviji) drajver za mysql bazu, koji omogucava neke bitne stvari, recimo prepare statements i da se logujes u bazu sa novim sistemom cuvanja sifri koji je sigurniji. Ali jos bolje je da umesto mysqli odmah preskocis i naucis PDO, to je isto drajver, ali ne samo za mysql, vec podrzava razne baze.

Sto se tice multi-query postoje neke sigurnosne implikacije sa tom f-jom, pa se zato ne preporucuje, a sem toga to nije ono sto tebi treba.

Bitno je da razumes kako se SQL izvrsava: php posalje svom drajveru SQL string koji si zadao, on to prosledi bazi, baza kompajlira SQL string u komandu i onda je izvrsi. Kad imas vise komandi njih moras da izvrsis sekvencijalno, jednu po jednu, i svaka ce proci kroz sve ove korake. Ono sto multiquery pomaze je sto mozes u jednom pozivu bazi da posaljes vise komandi, pa stedis na konekcijama ka bazi, koje su inace najsporiji deo operacije. Ali posle toga se sve odvija isto, tj. i dalje se izvrsava jedna po jedna komanda

Druga stvar koju treba da razumes je pojam atomske operacije u bazi. To je operacija koju mozes da zamislis da se obavlja u jednom koraku, tj. ona ili ne uspe, ili se izvrsi onako kako je zadano, druge operacije koje se izvrsavaju u bazi ne mogu da uticu na njen rezultat. U mysql-u je svaka pojedina komanda atomska, znaci ako kazes UPDATE tabela SET a=5, b=6; ti znas da ce na svakom redu u tabeli a i b biti toliko, ne moze da se promeni samo a ili samo na par redova.

Medjutim kad imas vise komandi onda to ije atomska operacija, znaci bilo kakve izmene u bazi koje neko drugi radi mogu da ti uniste relacije (veze id-jeva koje imas, sto se jednim imenom zove referencijalni integritet baze). Da se to ne bi desilo koriste se transakcije, a posto koristis InnoDB engine ja bih ti preporucio da sve te svoje operacije zatvoris izmedju START TRANSACTION i COMMIT komandi. Vise o tome mozes da procitas ovde:
http://dev.mysql.com/doc/refman/5.0/en/commit.html

slavkan 24. 09. 2011. 14:43

Hvala na korisnim informacijama. Iskren da budem iako sam transakcije malo proucavao na faxu i kao rauzmeo tad nesto sad nebih znao primeniti niti jednu na ovaj moj problem iako sam pogledao ovaj link. Znam da je to kao jedan od nasigurnijih nacina upravljanja bazama podataka i da se koristi recimo u bankama.

Sto se tice ovog mog problema meni ne treba sad nesto toliko efikasno resenje, mada sto ti rece treba ovo sve preskociti i baviti se ovim efikasnijim nacinima upravljanja bazama al eto treba nauciti i ove skolske primere pa onda preci na ono sto se u praksi primenjuje. Ako imas jos negde konkretnih primera primena transakcija na neke upise postavi, mozda kad ovo zavrsim bas krenem da se bavim time.

Sto se tice ovih mojih upita imao bih jos jedno pitanje. Posto meni treba da upisem podatke prvo u jednu pa u drugu tabelu, ne istovremeno :D , da li ovaj primer sto je webarto naveo moze da se primeni u mom slucaju:


Kôd:

$query = "INSERT INTO proizvodi(naziv_proizvoda,stanje) VALUES('kompujtor', 5);
INSERT INTO proizvodi_kategorije(Kategorija_idKategorija,Proizvod_idProizvod) VALUES(1, (SELECT LAST_INSERT_ID()));";

mysqli_multi_query($link , $query);

Dakle da smestim 2 inserta u jedan $query i ako je to moguce da li je sintaksa ista kao i ovde. Ali pitanje je, sve da je to moguce, da li tako mogu da dodjem do ovog mog idProizvoda sto mi treba jer njega treba iscupati posle prvog inserta pa onda odraditi drugi insert. Ipak nema logike, jel tako? To kad bi moglo dobro bi bilo za neke druge upite gde su svi podaci koji se upisuju u tabele odmah, da kazem "poznati" .

webarto 24. 09. 2011. 14:50

Uradi kako sam ti prvo napisao, znači uzmi ID u $id varijablu, možeš i ovo drugo ali je nepotrebno komplikovanje, ništa ne dobijaš osim veće šanse za greške. Htio sam ti samo reći da ne možeš 2 INSERTa u 2 tabele uraditi u jednom queryu, u svakom slučaju su 2 querya. Ovaj drugi primjer bi trebao isto da radi.

U drugom INSERTu ima SELECT koji kupi zadnji ID odosno taj idProizvod...

PHP kôd:

(SELECT LAST_INSERT_ID()) 



Vreme je GMT +2. Trenutno vreme je 05:50.

Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.

Mišljenja, saveti, izjave, ponude ili druge informacije ili sadržaji nastali na Sajtu su vlasništvo onoga ko ih je kreirao, a ne DevProTalk.com, tako da ne morate da se oslanjate na njih.
Autori poruka su jedini odgovorni za ovakve sadržaje. DevProTalk.com ne garantuje tačnost, kompletnost ili upotrebnu vrednost informacija, stavova, saveta ili datih izjava. Ne postoje uslovi pod kojima bi mi bili odgovorni za štetu ili gubitak koji je posledica bilo čijeg oslanjanja na nepouzdane informacije, ili bilo kakve informacije nastale kroz komunikaciju između registrovanih članova.
Web sajt može sadržavati linkove na druge web sajtove na Internetu ili neke druge sadržaje. Ne kontrolišemo niti podržavamo te druge web sajtove, niti smo pregledali bilo kakve sadržaje na takvim sajtovima. Mi nećemo biti odgovorni za legalnost, tačnost ili prikladnost bilo kog sadržaja, oglasa, proizvoda, usluga ili informacije lociranim na ili distribuiranih kroz druge web sajtove, niti za bilo kakvu štetu nastalu kao posledica takvih informacija. DevProTalk.com drži i čuva druga prava vlasništva na web sajtu. Web sajt sadrže materijale zaštićene copyright-om, zaštitne znakove i druge informacije o pravu vlasništva ili softver. Članovi mogu poslatu informacije zaštićene pravima vlasništva njihovih nosilaca i ona ostaju zaštićena bez obzira da li su oni koji prenose te informacije to naveli ili ne. Osim informacija koje su u javnom vlasništvu ili za koje dobijete dozvolu, nemate pravo da kopirate, modifikujete ili na bilo koji način menjate, objavljujete, prenosite, distribuirate, izvršavate, prikazujete ili prodajte bilo koju informaciju zaštićenu pravima vlasništva. Slanjem informacija ili sadržaja na bilo koji deo DevProTalk.com, Vi automatski dozvoljavate i predstavljate garanciju da imate pravo da dozvolite DevProTalk.com ili članovima DevProTalk.com bespovratnu, kontinualnu, neograničenu, globalnu dozvolu da koriste, kopiraju, izvršavaju, prikazuju i distribuiraju takve informacije i sadržaje i da iz takvih sadžaja koriste bilo koji deo u bilo koje svrhe, kao i pravo i dozvolu da koriste gore navedene sadržaje. Svi zaštitni znakovi (trademarks), logotipi, oznake usluga, firme ili imena proizvoda koji se pominju na ovom web sajtu su vlasništvo kojim raspolažu njihovi vlasnici.