PDA

View Full Version : INNER JOIN u INSERT INTO metodi?


mates
08-06-2007, 20:56
Pokusavam koristiti ASP i MySQL.
Javlja mi greske ako zelim upisati u bazu na ovaj nacin, dok u Access bazi radi super??
.................................................. ...................
SQL = "SELECT * FROM user INNER JOIN sell ON user.nruser = sell.nruser WHERE 1=2"

rs.Open SQL, MojaKon

rs.AddNew

rs("blabla") = blabla
rs("blabla") = blabla
rs("blabla") = blabla
rs("blabla") = blabla
rs("blabla") = blabla
rs("blabla") = blabla

rs.Update

rs.Close
MojaKon .Close
set MojaKon = nothing
.................................................. ...................

Poslje istrazivanja uvidio sam da MySQL ne voli Update metodu i da mnogi drugi u slicnoj situaciji prelaze na INSERT INTO metodu upisa.

E sad, kako koristit INNER JOIN u INSERT INTO metodi??

Ovako ne ide:
SQL = "INSERT INTO user INNER JOIN sell ON user.nruser = sell.nruser WHERE 1=2 (blabla,blabla,blabla) VALUES (blabla,blabla,blabla);"

Ja prosto moram ovako uradit, jer u protivnom bi trebao mjenjat strukturu cijele baze.

Ibiza
08-06-2007, 21:08
1 nikad nije jednako 2, pa ni nećeš dobiti nikakve rezultate...
Reci šta pokušavaš?

tsereg
08-06-2007, 22:12
INNER JOIN (ili bilo kakav join) stvara, možemo tako reći, "virtualnu" tablicu koja sadrži atribute jedne i druge tablice. Dodavanjem zapisa u tu virtualnu tablicu se dodaju zapisi u jednu i drugu stvarnu tablicu.

U Accessu ponekada možemo dodati zapis u takvu virtualnu tablicu - ali samo ponekada, u situaciji koja je opisana u Accessu u Helpu.

Iznenadilo bi me da MySQL dopušta tako nešto.

Moj savjet je da ne koristiš takav način dodavanja zapisa - vrlo je vjerojatno da radiš logičku grešku koje nisi niti svjestan - npr. da dodavanje jednog zapisa u tu virtualnu tablicu zapravo zahtijeva dodavanje više od jednog zapisa u jednu od stvarnih tablica.

Ako gornje nije slučaj, tj. ako se dodavanje jednog zapisa u takvu virtualnu tablicu uvijek svodi na dodavanje po jednog i točno jednog zapisa u svaku od stvarnih tablica, onda nikakvog razloga nemaš dodavati kroz JOIN. Dodaj zapis s dvije INSERT naredbe odvojeno u svaku tablicu, a za potrebe atomarnosti koristi transakcije (ako ih MySQL ima) ili zaključavanje obiju tablica prije dodavanja.

tsereg
08-06-2007, 22:14
P.S. rs.Update i SQL "UPDATE" nisu nužno ista stvar. UPDATE će se izvesti ako si otvorio sa rs.Edit, a ako si otvorio sa rs.AddNew, onda bi rs.Update u svakom slučaju trebao rezultirati s INSERT.

mates
11-06-2007, 09:48
Dodaj zapis s dvije INSERT naredbe odvojeno u svaku tablicu, a za potrebe atomarnosti koristi transakcije (ako ih MySQL ima) ili zaključavanje obiju tablica prije dodavanja.

Tako sam uradio i radi. Okej.
Ali drugi dio problema je ostao, naime kada sam izvrsio upis u tabelu1 zelim definirat jednu vrijednost iz tog aktualnog upisa i koristit ga odmah u sljedeci upis u tabeli2.

Kontraverzna vrijednost je u stvari broj/index iz tabele1 koji sam prije koristio kroz ranije spomenuti INNER JOIN.

<%
''''''''''''''''''''''''''''''''''''''otvorim kon prvi put i izvrsim upis'''''''''''''''''''

set Mojakon=server.createobject("adodb.connection")
Mojakon.Open="................;"

Set rs = Server.CreateObject("ADODB.Recordset")

SQL = "INSERT INTO tabela1 (, , , , , , ) VALUES (, , , , , , );"
rs.Open SQL, Mojkon


rs.Close
Mojakon.Close
set Mojakon= nothing


''''''''''''''''''''''''''otvorim kon drugi put i selektiram vrijednost iz prve tabele1, tj. iz zadnjeg upisa,
''''''''''''''''''''''''''potom definiram varijablu koju zelim koristit u drugom upisu, i na kraju pokusam izvrsit upis

set Mojakon=server.createobject("adodb.connection")
Mojakon.Open="................;"

Set rs = Server.CreateObject("ADODB.Recordset")

SQL = "SELECT nrindex FROM tabela1 ORDER BY nrindex desc;"
dim mojindex
mojindex = rs("nrindex")

SQL = "INSERT INTO tabela2 (, , , , , , ,mojindex) VALUES (, , , , , ,mojindex);"

rs.Open SQL, Mojakon

rs.Close
Mojakon.Close
set Mojakon= nothing

%>

tsereg
11-06-2007, 12:25
Kada, recimo, radiš s Accessom, čim napraviš AddNew nad tablicom koja ima "autoincrement" polje, odmah možeš iz objekta očitati vrijednost tog polja - ne treba raditi Update, pa potom sa SELECT očitavati.

Sumnjam da je u MySQL-u tako, pa je ova logika koju si zamislio OK.

Kod ti je totalno zbrljan. Nisam siguran da INSERT i UPDATE upite izvodiš s "Open" (zar nema Execute metoda ili sl.?). A ono što izvodiš s Open, a to je SELECT upit, to uopće nisi izveo. Staviš tamo neku varijablu SQL na "SELECT ... blabla", nigdje ne otvoriš recordset, a odmah ga ideš čitati...

TVOJA je zadaća osigurati da uopće znaš kako se programskim kodom realizira neka zamisao, pa to sredi prvo.

---

Što se logike tiče, ona je skoro dobra. Nedostaje ti zaključavanje tablica. Naime, ako dva posjetioca uzrokoju dodavanje zapisa u prvu tablicu gotovo istodobno, obadva će dobiti isti index u drugoj tablici... Moraš zaključati obje tablice, odraditi posao, otključati tablice.

mates
11-06-2007, 13:46
Uh, baš si me naružio "tsereg" :(

Idem to pokušat odradit, pa ću se javit sa rezultatom...

mates
11-06-2007, 14:42
Evo ga, radi. Super.
Tvoji savjeti su sluzili svrsi.
--------------------------------------------------------------------------------

set Mojakon=server.createobject("adodb.connection")
Mojakon.Open="................;"

Set rs = Server.CreateObject("ADODB.Recordset")

SQL = "SELECT nrindex FROM tabela1 ORDER BY nrindex desc;"
rs.Open SQL, Mojakon
'''''''''''''''''''nisam siguran da li bih trebao ogranicit zadnji upis, sa LIMIT 0, 1 ili
'''''''''''''''''''je ovako vec okej, mislim da li postoji mogucnost za neku gresku

SQL = "INSERT INTO tabela2 (, , , , , , ,mojindex) VALUES (, , , , , , '" & rs("nrindex") & "');"
Set Rs = MojaKon.Execute(SQL)

rs.Close
Mojakon.Close
set Mojakon= nothing

%>
-----------------------------------------------------------------------

E sad, zelio bih znati sto mislis o ovakvom rijesenju i na koji nacin da zakljucam/otkljucam tablice i kako ce se to odrazit na slucaje kada vise korisnika zeli poslati upis u bazu...

tsereg
11-06-2007, 14:57
Ne znam kako se zaključavaju tablice, tj. točnu sintaksu. Odi na web-stranice MySQL-a i malo prouči dokumentaciju. Sigurno je nešto oblika LOCK TABLES t1, t2; i UNLOCK TABLES .... Onda moraš vidjeti kako da izvedeš tu naredbu preko ADO-a (Command objekt, Execute metoda, što li i kako li...). Nisam nikada radio s MySQL-om, a sigurno ne preko ADO-a, tako da ti ne mogu dati konkretnije naputke.

Kada više korisnika radi s bazom, može se desiti ovo:

KORISNIK 1 doda zapis u tabelu 1 s indeksom 100.
KORISNIK 2 doda zapis z tabelu 2 s indeksom 101.
KORISNIK 1 izvede SELECT nrindex... i očita da je zadnji nrindex 101.
KORISNIK 1 doda u tabelu2 zapis koji se spaja s indeksom 101.
KORISNIK 2 izvede SELECT nrindex... i očita da je zadnji nrindex 101.
KORISNIK 2 doda u tabelu2 zapis koji se spaja s indeksom 101.

Očigledno, ovo je krivo. Vjerojatnost da se tako nešto dogodi je malena, pa ti možda za svoj programčić uopće ne želiš to raditi. No, ispravno rješenji bi bilo da se tablice zaključaju, obavi cijela procedura i potom otključaju. Ukoliko tijekom izvođenja te operacije neki drugi korisnik pokuša učiniti isto, prilikom pokušaja zaključavanja desit će se pogreška. Kod to treba detektirati i javiti korisniku poruku da pokuša ponovo (to će se desiti vrlo rijetko). Alternativno, moguće je tako konfigurirati stvar da kada drugi korisnik pokuša zaključati tablice (koje su već zaključane) uđe u red čekanja gdje će ostati "visiti" dok prvi korisnik ne otključa tablice (to će se desiti brzo, jer je operacija kratka).

Za detalje oko zaključavanja tablica se raspitaj u priručniku za MySQL.


Inače, trebaš vidjeti i što će se desiti ako korisnik zaključa tablice, a program se onda sruši zbog neke pogreške - hoće li tablice ostati zaključane, hoće li MySQL to detektirati i skinuti stanje zaključanosti... Uoči da u takvoj situaciji imaš problem i sa drugim stvarima, ne samo sa zaključavanjem tablica - općenito, imaš problem sa gubitkom integriteta podataka. Zato se u bazama podataka koriste transakcije (ali MySQL ih nema). Jedna od kompliciranijih zadaća kod programiranja je upravo oporavak od pogrešaka.

mates
11-06-2007, 19:18
Hm, pa ja se upravo trudim da predjem na bolju bazu podataka,
sa Access na MySql. Pa zar MySql nije napredniji u svim segmentima?

Htio bih te pitati i za ideju/scenario upisa podataka u bazu s tim da se sa svim ovim uobicajenim textualnim poljima salje i slika, direktno u bazu (MySql ima specijalno polje za slike pod nazivom BLOBB) ili u neku mapu, a ime, tj. URL do slike se upisuje u bazu.

Znam jedan takav nacin za slanje slika u mapu za slike, dok se URL do slike upisuje u bazu, ali ne mogu to spojit sa ovom obicnom upload aplikaijom.