Toon posts:

[perl/mysql] unieke userkey

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik gebruik de volgende code om voor iedere inschrijving een uniek nummer te genereren
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
my $gen;
my $count = 1;
my $sth;
my $dbh  = DBI->connect($database,$db_user,$db_password);
my $resno;
while ($count > 0)
{
      $gen = int(rand 8999999) + 1000000;
      
      my $row;
      my $query = "SELECT COUNT(userkey) FROM mailinglist WHERE userkey LIKE '%$gen%'";
       $sth=$dbh->prepare("$query");
      $sth->execute();
      $sth->bind_columns(undef, \$resno);
      $count = 0;
      $row = $sth->fetchrow_arrayref;
     if ($resno > 0)
             {
                 $count = 1;
             }
}
$sth->finish();
$dbh->disconnect();
return ($gen);

De volgende userkey: 8388607 komt 5 keer voor in ca. 100 records. Nogal vreemd als er 8999999 mogelijkheden zijn.

Waar sla ik de plank mis!

Verwijderd

waarom gebruik je niet gewoon een autoincrement ipv dat je ze zelf genereerd?

Verwijderd

Topicstarter
Op maandag 03 juni 2002 19:09 schreef Foxboy het volgende:
waarom gebruik je niet gewoon een autoincrement ipv dat je ze zelf genereerd?
omdat ik deze subroutine ook gebruik voor ordernummers van bestellingen en die wil ik niet opvolgend hebben maar random

Verwijderd

mpffff,
bij mij werkt het best.
anders neem je een timestamp en gooi je daar ene wiskundige bewerking overheen?

Verwijderd

Topicstarter
Op maandag 03 juni 2002 19:16 schreef Foxboy het volgende:
mpffff,
bij mij werkt het best.
anders neem je een timestamp en gooi je daar ene wiskundige bewerking overheen?
Dat nummer genereren gaat wel goed. Ik wil alleen weten waarom hij dubbele doorlaat. De code voor het controleren van het nummer zou toch moeten werken zo.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op maandag 03 juni 2002 19:11 schreef zzzflitzzz het volgende:
omdat ik deze subroutine ook gebruik voor ordernummers van bestellingen en die wil ik niet opvolgend hebben maar random
Wat is het nut ervan om die random te hebben :?

Verwijderd

als je gewoon een timestamp neemt (... seconden sinds het jaar 1970) die is altijd verschillend hoef je ook geen kostbare query's uit te voeren op je mysql databeest

Verwijderd

Topicstarter
Op maandag 03 juni 2002 19:39 schreef Foxboy het volgende:
als je gewoon een timestamp neemt (... seconden sinds het jaar 1970) die is altijd verschillend hoef je ook geen kostbare query's uit te voeren op je mysql databeest
Is niet uniek.
Op maandag 03 juni 2002 19:33 schreef ACM het volgende:

[..]

Wat is het nut ervan om die random te hebben :?
De vraag is waarom ik dubbelen heb, wat is er fout aan mijn code. Het nut van random staat hier volgens mij buiten.

  • Brakkie
  • Registratie: Maart 2001
  • Niet online

Brakkie

blaat

Op maandag 03 juni 2002 19:45 schreef zzzflitzzz het volgende:

[..]

Is niet uniek.
[..]

De vraag is waarom ik dubbelen heb, wat is er fout aan mijn code. Het nut van random staat hier volgens mij buiten.
Kan zijn dat iemand er gewoon benieuwd naar is :?

Systeem | Strava


Verwijderd

Topicstarter
Op maandag 03 juni 2002 19:48 schreef brakkie het volgende:

[..]

Kan zijn dat iemand er gewoon benieuwd naar is :?
Okay dan, bij order nummers werken we per maand in verschillende rangen en om typo's te voorkomen voor reserveringsmedewerkers moet hij random zijn.

  • corani
  • Registratie: December 2000
  • Laatst online: 05-10-2017

corani

__,,,_(^_^)_,,,__

Op maandag 03 juni 2002 19:07 schreef zzzflitzzz het volgende:
code:
1
2
3
4
5
6
7
8
9
10
11
  .
  .
  .
  my $query = "SELECT COUNT(userkey) FROM mailinglist WHERE userkey LIKE '%$gen%'";
  .
  .
  .
 if ($resno > 0)
 {
        $count = 1;
 }
Waarom LIKE?

en moet je $count niet op 1 zetten als $resno nul is?

Laat me nou toch eens met rust man!
Iedereen die in telekinese gelooft, steek a.u.b. mijn hand op


Verwijderd

Topicstarter
Op maandag 03 juni 2002 19:57 schreef corani het volgende:

[..]

Waarom LIKE?

en moet je $count niet op 1 zetten als $resno nul is?
LIKE heb ik gebruikt omdat hij dubbelen toeliet.
Als $resno nul is moet hij de loop verlaten en dus 0 blijven.

  • corani
  • Registratie: December 2000
  • Laatst online: 05-10-2017

corani

__,,,_(^_^)_,,,__

Edit: Iets doms

Laat me nou toch eens met rust man!
Iedereen die in telekinese gelooft, steek a.u.b. mijn hand op


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Moet je je random waarde niet eerst seeden (zie uitleg over srand en rand)?

Maar goed, het nut van random key's was gewoon uit nieuwsgierigheid :)
Alhoewel het nut me nog niet helemaal duidelijk is, maar dat zal komen omdat ik er 'niet bij was' :)

Verwijderd

seeden gaat automatisch zinds een heel aantal perl versies geleden.

Verwijderd

hè???
code:
1
while ($count > 0)

blijf in de loop als $count groter wordt dan nul,

code:
1
if ($resno > 0) { $count = 1; }

als $resno groter is dan nul (er is 1 of meer dubbele) ga uit de loop, het moet toch andersom?????

Verwijderd

Topicstarter
code:
1
while ($count > 0)

Zolang $count groter is dan nul moet deze loop uitgevoerd worden.

code:
1
if ($resno > 0) { $count = 1; }

Als een nummer gevonden is wordt $count 1 en voldoet daarmee aan de voorwaarde om de loop nog een keer te doorlopen

Dus als een nummer gevonden wordt zal de loop nog een keer uitgevoerd worden.

Ik hoop zo dat hij een beetje duidelijk voor je is.

Verwijderd

mjah ik zie me eigen fout
beetje brakke constructie btw

Verwijderd

Topicstarter
Op dinsdag 04 juni 2002 14:44 schreef Foxboy het volgende:
mjah ik zie me eigen fout
beetje brakke constructie btw
Als je een betere constructie weet kom maar op
Ik weet trouwens nog steeds niet waarom hij dubbele doorlaat

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 06-09 14:04

Creepy

Tactical Espionage Splatterer

Als seeden automatisch gaat, krijg je voor elke keer dat je script start dus een andere seed.

Waarschijnlijk gaat dit seeden a.d.v. de tijd, dus als je bijv. elke second je script start zul je zien dat je geen fatsoenlijke random waarden krijgt, aangezien om de zoveel tijd dezelfde seed, en daardoor ook dezelfde random waarde voorbij komt.

Als je in 1 script 100 keer rand() aanroept, krijg je zeer waarschijnlijk wel 100 unieke waarden.

Is het niet makkelijker om een auto_increment veld te gebruiken? Dan geeft de DB altijd een unieke waarde terug, je moet alleen wel ff letten op locking zodat als er twee gebruikers in je DB bezig zijn, ze niet hetzelfde ID terug krijgen.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

dat was dus niet de vraag
het gaat erom dat de code niet werkt.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 06-09 14:04

Creepy

Tactical Espionage Splatterer

Op dinsdag 04 juni 2002 16:40 schreef Foxboy het volgende:
dat was dus niet de vraag
het gaat erom dat de code niet werkt.
Eehh... de rest van mijn reply ook gelezen? Ik heb uitgelegd waarom je ZEER WAARSCHIJNLIJK die dubbele unieke key's hebt, met daarnaast een oplossing (wel compleet anders dan die van jou) om het probleem te voorkomen.
Dan heb je dus ook de code niet meer nodig om te checken op dubbele waarden.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

snel effe editten he :+
ik heb geen zin om een flame war te beginnen,
maar lees de draad voordat je blaat
autoincrement veld had ik het al over in de 1e reply op dit topic. dat is dus geen optie omdat de waardes niet opeenvolgend mogen zijn

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 06-09 14:04

Creepy

Tactical Espionage Splatterer

*whoops* ja

liet me ff afleiden door "De volgende userkey: 8388607 komt 5 keer voor in ca. 100 records. Nogal vreemd als er 8999999 mogelijkheden zijn."

edit:
(en weer een snelle edit :) )
Maaruh.. kan het niet zo zijn dat op nagenoeg hetzelfde moment door 2 medewerker wordt uitgevoerd, zodat die check op dat dubbele nummer tegelijk wordt uigevoerd, en dus nog niet in de DB staat...en dus 2 keer hetzelfde in de DB geschreven word.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Topicstarter
Op dinsdag 04 juni 2002 18:58 schreef Creepy het volgende:
*whoops* ja

liet me ff afleiden door "De volgende userkey: 8388607 komt 5 keer voor in ca. 100 records. Nogal vreemd als er 8999999 mogelijkheden zijn."

edit:
(en weer een snelle edit :) )
Maaruh.. kan het niet zo zijn dat op nagenoeg hetzelfde moment door 2 medewerker wordt uitgevoerd, zodat die check op dat dubbele nummer tegelijk wordt uigevoerd, en dus nog niet in de DB staat...en dus 2 keer hetzelfde in de DB geschreven word.
Nee er zitten soms dagen tussen en toch weer steeds 8388607

Verwijderd

Als je nou toch gewoon een UNIX-timestamp pakt, (zoals al eerder gezegd), en je prefixt en postfixt er een random getal aan dan is het toch behoorlijk uniek zou ik zo zeggen?!

Verwijderd

Topicstarter
Op dinsdag 04 juni 2002 22:36 schreef zellufs het volgende:
Als je nou toch gewoon een UNIX-timestamp pakt, (zoals al eerder gezegd), en je prefixt en postfixt er een random getal aan dan is het toch behoorlijk uniek zou ik zo zeggen?!
Okay en dan moet ik toch weer uitkomen op een getal van 7 cijfers en hoe ik dat getal genereer is mij nu wel duidelijk.
Waarom laat mijn while loop dan dubbelen door is eigenlijk de vraag.

  • Sponz
  • Registratie: Juni 2001
  • Niet online

Sponz

nul nest parfait saif moi

Je moet een database bijhouden met de uitgegeven random getallen. Random is namelijk niet echt random!

Met elk nieuw random getal moet je kontroleren of ie al uitgegeven is.

Verwijderd

ja, dat doet ie ook. Het werkt alleen niet.
In Perl weet ik het niet maar in PHP zou ik anders met die while omgaan. Ik snap ook eerlijk gezegd nog steeds niet waarom die COUNT en die LIKE gebruikt wordt.

Waarom niet gewoon een while lus waarin je blijft totdat mysql_num_rows 0 is?
Dus eerst die random $gen genereren en dan:

"SELECT * FROM mailinglist WHERE userkey='$gen' LIMIT 1"

of zoiets

(dus niet met COUNT en LIKE enzo)

Als je niks terug krijgt uit je SELECT, komt hij dus uit de lus en heb je dus een unieke. Zo niet, doet hij het hele riedeltje nog een keer.

  • Ees
  • Registratie: Juli 2001
  • Laatst online: 29-07 15:00

Ees

> my $dbh = DBI->connect($database,$db_user,$db_password);

Zet RaiseError en PrintError eens aan:

...connect($db,$u,$p,{RaiseError => 1, PrintError => 1})

> my $query = "SELECT COUNT(userkey) FROM mailinglist WHERE userkey LIKE '%$gen%'";

Waarom niet "COUNT( * )"? En die "LIKE" moet je inderdaad maar weer veranderen...

> $sth->bind_columns(undef, \$resno);

Ik weet het niet zeker (en ben te lui om het echt op te zoeken), maar gaat dit niet mis? Je "select" 1 column, en je "bind" aan twee.

Verwijderd

Topicstarter
ik heb geprobeerd info te vinden over PrintError en RaiseError maar kan er bij de MySQL website en in mijn boeken er niets over vinden. :'( Als je hier enige uitleg over zou hebben graag. :)

  • Ees
  • Registratie: Juli 2001
  • Laatst online: 29-07 15:00

Ees

Nee, die horen bij DBI: man DBI dus :)

Verwijderd

wat staat er in $resno?
Zeker weten dat het resultaat van je COUNT() daar in komt te staan?

Verwijderd

Topicstarter
Op woensdag 05 juni 2002 11:30 schreef MarcoTC het volgende:
wat staat er in $resno?
Zeker weten dat het resultaat van je COUNT() daar in komt te staan?
Ja, 100% zeker


DBI: dus. You rule, EES bedankt *D

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 28-08 12:00

Janoz

Moderator Devschuur®

!litemod

Wat ik persoonlijk vreemd vind, is dat je met timestamp denkt dat je dubbele kunt krijgen (wat redelijk onwaarschijnlijk is aangezien het script dan in dezelfde miliseconde uitgevoerd moet worden), terwijl deze methode ook gewoon dubbele keys doorlaat. Wat nu als het script gelijktijdig wordt aangeroepen en hetzelfde getal genereerd (wat niet ondenkbaar is) dan zal beide keren de check terug geven dat het getal goed is aangezien het nummer nog niet in de DB staat, en zullen er alsnog dubbele nummers zijn.

Ikzelf zou dit soort dingen zoveel mogelijk door de DB laten afvangen. Door het veld uniek te maken is het onmogelijk om dubbelen te krijgen. Door bij het inserten te kijken of het mis gegaan is (mysql geeft immers een nette error als er een dubbel veld geinsert probeert te worden) kun je op dat moment weer een nieuw ID genereren.

In principe werkt het dan op dezelfde manier als je huidige code, met het verschil dat je de DB op dubbele laat controleren ipv dit in je eigen code te doen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Topicstarter
Op woensdag 05 juni 2002 12:08 schreef Janoz het volgende:
Ikzelf zou dit soort dingen zoveel mogelijk door de DB laten afvangen. Door het veld uniek te maken is het onmogelijk om dubbelen te krijgen. Door bij het inserten te kijken of het mis gegaan is (mysql geeft immers een nette error als er een dubbel veld geinsert probeert te worden) kun je op dat moment weer een nieuw ID genereren.

In principe werkt het dan op dezelfde manier als je huidige code, met het verschil dat je de DB op dubbele laat controleren ipv dit in je eigen code te doen.
Klinkt goed, ik ga het proberen.
Bedankt *D

Verwijderd

Topicstarter
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
my $userkey;
my $error_code;
my $count = 1;
my $sth;
while ($count > 0)
{
      $count         = 0;
      $userkey   = int(rand 8999999) + 1000000;
    my $query    = "INSERT INTO mailinglist_demo(userkey, email, nonmail) VALUES (?,?,?)";
    $sth        = $dbh->prepare("$query");
    $sth->execute($userkey, $email, "0");
    $error_code  = $sth->err;
    if ($error_code > 0)
        {
            $count=1;
        }

    $sth->finish();
}

Dit moet de oplossing zijn. Ik ga alleen nog die random veranderen want het nummer wat hij gaf aan de eerste entry is 8388607 |:(

  • Ees
  • Registratie: Juli 2001
  • Laatst online: 29-07 15:00

Ees

Volgens mij zou het volgende ook ongeveer moeten werken (untested):
code:
1
2
3
4
5
6
7
8
9
10
my ($userkey, $error_code, $sth);
my $query    = "INSERT INTO mailinglist_demo(userkey, email, nonmail) VALUES (?,?,?)";
$sth        = $dbh->prepare("$query");

do {
  $userkey   = int(rand 8999999) + 1000000;
  $sth->execute($userkey, $email, "0");
  $error_code    = $sth->err;
  $sth->finish();
} while ($errorcode);

Iets logischer IMHO.

Over de niet-random userkey:
1. Welke versie van Perl draait er?
2. Gebruik je ergens in je code een srand-aanroep?

Verwijderd

Topicstarter
Ees, je hebt gelijk die code kan veel beter en schoner.

Welke versie van Perl er draait weet ik zo gauw niet. De hosting is van xs4all.
Ik gebruik geen srand.
Pagina: 1