Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: do-while ja mt_rand ongelma

Sivun loppuun

t0ll0 [22.08.2010 16:58:10]

#

Terve!

Olisi tarkoitus saada luotua "seurantanumero" joka on 10 numeroa pitkä luku ja tietenkin pitäisi varmistaa ettei tietokannasta löydy samanlaista lukua ja jos löytyy niin tekee uuden luvun ettei homma kuse.

Pitkällisten yritysten jälkeen päädyin käyttämään mt_randia ja do-while looppia.
Jostain syystä tällä koodilla formin jälkeen sivu jää junnaamaan paikoilleen?

Eli mikä kusee?
Ja jos jollakulla on parempi idea tämän asian toteuttamiseen niin saa todellakin ehdottaa!

Koodi näyttää tältä:

do {

	$trackingcode = mt_rand(0, 9);
	for($i = strlen($trackingcode); strlen($trackingcode) < 10; $i++){
		$trackingcode = $trackingcode . mt_rand(0, 9);
	}

$sql = mysql_query("SELECT * FROM works_tc WHERE trackingcode = '".$trackingcode."'",$lnk);
$sametc = mysql_num_rows($sql);


} while ($sametc == "0");

Vai olenko liian jumissa tajutakseni yksinkertaista virhettä.

-t0ll0

-tossu- [22.08.2010 17:18:25]

#

t0ll0 kirjoitti:

Ja jos jollakulla on parempi idea tämän asian toteuttamiseen niin saa todellakin ehdottaa!

Käytä AUTO_INCREMENT:iä ja laita luvun eteen tarpeeksi nollia.

t0ll0 [22.08.2010 17:29:33]

#

-tossu-

auto_increment olisi muuten kätevä tähän mutta tarkoituksena on luoda luku josta ei voi päätellä monesko rivi se tietokannassa on.


ps. hieman helpotin tuota 10 numeron luvun generointia..
eli for-silmukka pois ja tilalle mt_rand(1000000000,9999999999);

koodi näyttää nyt tältä:

do {

$trackingcode = mt_rand(1000000000,9999999999);

$sql = mysql_query("SELECT * FROM works_tc WHERE trackingcode = '".$trackingcode."'",$lnk);
$sametc = mysql_num_rows($sql);


} while ($sametc == "0");

ongelma ei silti poistunut... sivu junnaa edelleen!

-t0ll0

Grez [22.08.2010 17:31:22]

#

No voihan autoincrementinkin aloittaa vaikka luvusta 3910920192.

Tai sitten symmetrisellä salauksella muuntaa juoksevan numeron vähemmän juoksevan näköiseksi. Tosin en tiedä onko PHP:ssä tukea esim. millekään 32-bittiselle symmetriselle salausalgoritmille.

Jos haluat tuolla randomilla tehdä, niin laittaisin sinuna kantaan uniikkiavaimeksi sen seurantanumeron ja yrittäisin vaan insertata avaimia sinne kunnes onnistuu.

Ja BTW, toi numrowsin antaman luvun vertaaminen merkkijonoon näyttää todella perverssiltä, vaikka PHP sen salliikin. Samoin tuntuu hölmöltä että lataat sieltä kaikkien vastaavien rivien kaikki sarakkeet, vaikka oikeasti riittäisi tieto onko siellä sellaista vai ei.

Kaikesta huolimatta varsinainen ongelma on, että poistut loopista vasta jos siellä on ennestään se arpomasi koodi. Eli seuraava olisi varmasti toimivampi:

while ($sametc > 0);

t0ll0 [22.08.2010 17:34:41]

#

Grez

Tarkennan siis vielä.. vaikka auto_incrementin aloittaisi luvusta 436673836 niin silti siitä voisi päätellä kuinka monta riviä tietokantaan ilmestyy keskimäärin viikossa koska auto_increment nousee yhdellä ja tämä ei ole toivottu lopputulos.

-t0ll0


ps. works_tc ei sisällä muita tietoka kuin trackingcode sarakkeen joten hidastaako mikäli haen "kaikki" eli *?

enihau koodi näyttää nyt tältä eikä sivu junnaa:

do {

$trackingcode = mt_rand(1000000000,9999999999);

$sql = mysql_query("SELECT * FROM works_tc WHERE trackingcode = '".$trackingcode."'",$lnk);
$sametc = mysql_num_rows($sql);


} while ($sametc > 0);

Ja homma toimii!
kiitoksia

LaNu [22.08.2010 18:01:09]

#

t0ll0 kirjoitti:

ps. works_tc ei sisällä muita tietoka kuin trackingcode sarakkeen joten hidastaako mikäli haen "kaikki" eli *?

Grez vain vinkkasi, että on olemassa SQL-funktio COUNT. Jos laitat SQL:n laskemaan rivimäärän, tietokanta palauttaa vain yhden luvun. Sinun koodissasi koko taulun data lähetetään PHP:lle, joka tuloksesta sitten hakee rivimäärän eikä hyödynnä muuta dataa mitenkään.

Suorituskykyeroa syntyy, jos taulussa on riittävästi rivejä. Vaikkei tuo moka välttämättä koskaan aiheuta ongelmia, ei sitä noin kannata tehdä.

Grez [22.08.2010 18:24:39]

#

Niin, eihän tuolla ole mitään käytännön merkitystä. Toisaalta nyt joudun ihmettelemään, miksi taulussa ei ole mitään muita sarakkeita. Vaikuttaa melko hyödyttömältä taululta.

Toisaalta sitä suuremmalla syyllä voisi käyttää mallia, jossa taulun (ainoa) kenttä on unique ja arvottuja lukuja yritetään tallentaa kunnes onnistutaan. Näin kaksi käyttäjää ei missään tapauksessa voisi saada samaa seurantakoodia.

t0ll0 [22.08.2010 18:57:07]

#

LaNu

Aivan nyt ymmärsin.. Vaihdan tuon COUNTin nykyisen tilalle.

Grez
Taulussa ei ole muita sarakkeita koska trackingcode lisätään myös toiseen tauluun josta löytyy muut tiedot.

Ja miksikö se pitää tallentaa kahteen paikkaan?
Varmuuskopioinnin takia.
Vaikka tiedot poistetaan toisesta taulusta niin toiseen tauluun jää vielä se trackingcode varmistamaan ettei useamman varmuuskopioinnin jälkeenkään tule päällekkäisyyksiä.

-t0ll0

Grez [22.08.2010 19:27:04]

#

Niin, harmi ettei tuo koodisi takaa, etteikö samaa koodia voisi tulla kahteen kertaan.

Metabolix [22.08.2010 20:24:29]

#

Minusta kaikin puolin järkevämpi ratkaisu olisi luoda normaaliin tapaan id joka riville ja laskea siitä tuollainen mystisempi luku jollain kaavalla, joka tuottaisi taatusti jokaisesta id:stä eri luvun.

t0ll0 [22.08.2010 22:20:50]

#

Grez

Mitä tarkoitat?

Metabolix
Aluksi oli käytössä koodi joka hoiti tuon homman hyvin hankalasti.

Seurantaluku: XXXXXXXXXX

1. Kerrotaan timestampin minuutit sekunneilla (max. 59 x 59 = 3481)
2. Tuloksen eteen lisätään nollia siten että luvusta tulee jokatapauksessa nelinumeroinen
3. Luku lisätään kymmennumeroiseen seurantalukuun siten että joka toinen numero laitetaan seurantaluvun eteen ja joka toinen taakse kuitenkin jättäen kaksi viimeistä seurantaluvun numeropaikkaa avoimeksi
esim. 3481 = 38XXXX14XX
4. ID:stä tehdään viisinumeroinen luku lisäämällä nollia ensimmäisen numeron jälkeen mikäli id ei ole jo valmiiksi viisinumeroinen
esim. ID 293 = 20093
5. Viisinumeroinen id lisätään seurantalukuun käänteisesti siten että viides seurantaluvun numeropaikka jää vapaaksi
esim. 3839X01402
6. Seurantanumeron viidenteen numeropaikkaan lisätään tilauksen alkuperäisen id:n numeroiden lukumäärä.
esim. 3839301402

Luovuin kuitenkin tästä mm. järjettömyyden vuoksi ja tein homman mt_randilla. :)

-t0ll0

Grez [22.08.2010 22:35:34]

#

t0ll0 kirjoitti:

Grez
Mitä tarkoitat?

Jos ajatellaan että kaksi henkilö lataavat sivun suunnilleen samaan aikaan..

Hlö A:n sivulataus käynnistyy
Hlö A:lle arvotaan 1234567890
Hlö B:n sivulataus käynnistyy
Hlö A:n skripti tarkistaa, että 1234567890 on vielä vapaana
Hlö B:lle arvotaan 1234567890
Hlö B:n skripti tarkistaa, että 1234567890 on vielä vapaana
Hlö A:n 1234567890 tallennetaan kantaan
Hlö B:n 1234567890 tallennetaan kantaan

Kieltämättä melko epätodennäköistä, että kahdelle tulisi peräkkäin sama numero.

Vasta kahdessa viestissä tässä ketjussa olen kertonut miten se olisi järkevämpää toteuttaa vaikka mt_randia käyttäen.

t0ll0 [22.08.2010 22:44:17]

#

Grez

Otin kyllä avaimen jo käyttöön vielä varmistamaan luvun uniikkiuden.
Ihmettelinkin jo että mikä on vielä vituillaan, mutten sitä ollut kertonut.

Grez [22.08.2010 22:58:07]

#

No eikö tossa sitten olisi järkevämpää arvontaloopissa suoraan insertata sitä avainta kantaan ja katsoa onnistuuko, kuin vasta jossain vaiheessa myöhemmin kun sitä ei enää saada uudelleen arvottua ja joudutaan heittämään käyttäjälle virheilmoitus? Samalla jäisi pois aivan turha kannasta lukeminen.

t0ll0 [23.08.2010 10:08:40]

#

Grez

do {

$trackingcode = mt_rand(1000000000,9999999999);
$sql = mysql_query("INSERT INTO works_tc (trackingcode) VALUES ('".$trackingcode."')",$lnk);

} while (!$sql || mysql_affected_rows($lnk) > 1);

ja indeksinä
Avaimen nimi: trackingcode
Tyyppi: Unique
Sarake: trackingcode

Nyt ei pitäis olla mitään ongelmaa...
Eriäviä mielipiteitä?

-t0ll0


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta