[PHP] 4 numeri casuale no doppioni

bubino8

Utente Attivo
28 Apr 2017
360
20
28
29
BZ
Ciao,

Ho una tabella clienti e ad ognuno vorrei assegnare un id_cliente casuale NON id AutoIncrement!
Es: CC-7842

Vorrei fare in modo che quando creo un nuovo cliente mi genera in automatico un nuovo ID es. CC-9164 ma devo effettuare un controllo sul DB che se è già presente ne genera un altro e continua finche non ne trova uno non esistente.

Al momento ho fatto una base ma devo capire come fare il ciclo finche non trova un ID libero
PHP:
$numero = rand(1000,9999);
    $codcliente = "CC-".$numero;
        $string = "SELECT * FROM clienti WHERE CodiceCliente='".$codcliente."'";
        $query = mysql_query($string) or die (mysql_error());
        $quanti = mysql_num_rows($query);
        if ($quanti >=1) {
            echo "Esiste<br>";
            //Ciclo che continua finche non trova numero libero
        }else{
            echo "Cliente Creato<br>";
            $string2 = "INSERT INTO clienti (NomeAzienda, CodiceCliente) VALUES ('$numero', '$codcliente');";
            $query2 = mysql_query($string2) or die (mysql_error());
        }
Grazie a tutti in anticipo
 
Ultima modifica:

livellacri

Utente Attivo
18 Ago 2016
108
13
18
Potresti utilizzare un ciclo while che viene eseguito fino a quando la variabile $stop è uguale a 0.
Quando trova un codice libero, assegna valore 1 alla variabile, e il ciclo non viene più eseguito.
PHP:
$stop = 0;
while ($stop==0) {
    $numero = rand(1000,9999);
    $codcliente = "CC-".$numero;
    $string = "SELECT * FROM clienti WHERE CodiceCliente='".$codcliente."'";
    $query = mysql_query($string) or die (mysql_error());
    $quanti = mysql_num_rows($query);
    if ($quanti ==0) {
        echo "Cliente Creato<br>";
        $string2 = "INSERT INTO clienti (NomeAzienda, CodiceCliente) VALUES ('$numero', '$codcliente');";
        $query2 = mysql_query($string2) or die (mysql_error());
        $stop = 1;
    }
}

Ti ricordo che le funzioni di MySQL sono deprecate e rimosse dalla versione 7 di PHP, è meglio utilizzare MySQLi.
 

zorro

Utente Attivo
20 Ott 2014
279
15
18
ROMA
Ciao Bubino,
ammesso di aver bene interpretato ciò che intendi fare, ho fatto un po' di prove. Ho usato le nuove mysqli (sconsiglio di usare le ormai deprecate mysql). Ho creato anche una tabella di prova nella quale ho inserito diversi clienti con diversi codcli (x comodità tra 1 e 10). Ho provato prima con un codcli inesistente (10) e mi dice correttamente che non lo trova (non è duplicato) e poi con uno già esistente(4) e mi dice che già esiste e mi dice qual'è il primo codcli libero. Questo il codice


PHP:
<?php
$num = rand(1000,9999);
$codcli = 4;
//echo $codcli;

require('conn.php');

//---------------LEGGE LA TABELLA----------------

$connessione = new mysqli($host, $user, $password, $db);

// verifica su eventuali errori di connessione
if ($connessione->connect_errno) {
    echo "Connessione fallita: ". $connessione->connect_error . ".";
    exit();
} else {
    echo 'Connessione col DB correttamente riuscita!!!!<br>';
}

if (!$result = $connessione->query("SELECT * FROM CLIENTI WHERE ID_CLI = '$codcli'")) {
    echo "Errore della query: " . $connessione->error . ".";
} else {
    // conteggio dei record
    if ($result->num_rows > 0) {
       // conteggio dei record restituiti dalla query
       $row = $result->fetch_array(MYSQLI_ASSOC);
      
       echo 'ATTENZIONE!! Codice '.$codcli.' già presente nel DB';   
       $codcli=1;
       //echo 'codicev cercatoù: '.$codcli;
       $libero = 0;
       while ($libero == 0) {
             if (!$result = $connessione->query("SELECT * FROM CLIENTI WHERE ID_CLI = '$codcli'")) {
                 echo "Errore della query: " . $connessione->error . ".";
             } else {
                 // conteggio dei record
                 if ($result->num_rows > 0) {
                     // conteggio dei record restituiti dalla query
                     $row = $result->fetch_array(MYSQLI_ASSOC);
                     $codcli++;
                 } else {
                     $libero=1;   
                     echo '<br>primo codice libero trovato: '.$codcli;
               }
             }
       }     
    } else {
       echo 'Codice NON trovato';
       echo '<br>codice cliente: '.$codcli;
    }
}
// liberazione delle risorse occupate dal risultato
       $result->close();
?>


Ovviamente io ho cercato di semplificare al massimo le cose, tu dovrai adattarlo alle
tue esigenze.


Zorro
 

marino51

Utente Attivo
28 Feb 2013
3.041
192
63
Lombardia
@livellacri , @zorro
vorrei chiedervi la cortesia di rispondere alle mie domande (curiosità / conoscenza),
Bubino ritiene di inserire al massimo 8000 clienti "rand(1000,9999)"
quanti rand deve generare e quante verifiche nel database deve fare per ottenere il codice dell' "ultimo" cliente da inserire ?
mi spingo a dire, riuscirà mai ad ottenerlo ?
io credo che il limite di questo agire, sia la non uniforme distribuzione dei numeri generati
ovvero il sistema potrebbe rallentare in maniera notevole dopo un certo numero di rand generati
vero / falso ?
il "rand" potrebbe anche avere la stessa sequenza ad ogni riavvio dello script, rallentando il processo vero / falso ?
 

livellacri

Utente Attivo
18 Ago 2016
108
13
18
quanti rand deve generare e quante verifiche nel database deve fare per ottenere il codice dell' "ultimo" cliente da inserire ?
Essendo numeri casuali, è impossibile dirlo con precisione...

mi spingo a dire, riuscirà mai ad ottenerlo ?
io credo che il limite di questo agire, sia la non uniforme distribuzione dei numeri generati
ovvero il sistema potrebbe rallentare in maniera notevole dopo un certo numero di rand generati
vero / falso ?
Probabilmente lo otterrà, ma come hai detto te, ci potrebbe volere molto tempo per trovare gli ultimi numeri.
Anche se forse molto meno di quanto pensiamo... con il computer che sto utilizzando adesso (poco potente), ho provato a fare un ciclo for che ripete una query 9999 volte, ed inpiega circa 2 secondi.
Comunque una scelta saggia sarebbe, quando mancano pochi numeri, aumentare il range.

il "rand" potrebbe anche avere la stessa sequenza ad ogni riavvio dello script, rallentando il processo vero / falso ?
Questo immagino sia praticamente impossibile

edit: @marino51 le tue domande mi hanno fatto riflettere molto... ora provo a fare dei test
 
Ultima modifica:

livellacri

Utente Attivo
18 Ago 2016
108
13
18
Allora... ho effettuato un test con questo script:
PHP:
<?php
set_time_limit(0);

$db = mysqli_connect("localhost", "root", "", "database");

for ($x=1; $x<=9000; $x++) {
    $start = microtime(true);
    $stop = 0;
    while ($stop==0) {
        $numero = rand(1000,9999);
        $codcliente = "CC-".$numero;
        $string = "SELECT * FROM table5 WHERE CodiceCliente='".$codcliente."'";
        $result = $db->query($string);
        $quanti = $result->num_rows;
        if ($quanti ==0) {
            $string2 = "INSERT INTO table5 (NomeAzienda, CodiceCliente) VALUES ('$numero', '$codcliente');";
            $db->query($string2);
            $stop = 1;
        }
    }
    $time_elapsed_secs = microtime(true) - $start;
    echo $x."; ".$time_elapsed_secs."\r\n";
}
?>

Nell'asse delle x il numero di codici già presenti nel db, nell'asse delle y i secondi impiegati.
La media è di 0.05 secondi, e per l'ultimo codice sono serviti 234 millesimi di secondo (0,234s)
ASC1Fht.png
 

marino51

Utente Attivo
28 Feb 2013
3.041
192
63
Lombardia
@livellacri
grazie per il tuo impegno,
il set è stato completato nel tempo da te indicato (pc con "centrino" ma ssd)
lo script ha fatto poco più di 20000 select (con picco di 280) per trovare gli 8000 numeri
"rand" è ben "distribuita", tutti i numeri sono stati generati
grazie ancora
 

bubino8

Utente Attivo
28 Apr 2017
360
20
28
29
BZ
Grazie a tutti per l'aiuto.
@marino51 in effetti non è il massimo potrei rischiare di rallentare tutto ma mi è stato richiesto in questo modo.

Per questione mysql mysqli grazie per avermelo fatto notare, so che non si usa più, ma su test in locale mi trovo più comodo e veloce.

Comunque una scelta saggia sarebbe, quando mancano pochi numeri, aumentare il range.

premetto che il raggiungere 8000 clienti sarà lunga, ma stavo già pensando ad un modo per renderlo automatico e aumentare appunto il range come dici tu.

Intanto grazie mille ancora a tutti.
 

marino51

Utente Attivo
28 Feb 2013
3.041
192
63
Lombardia
scusatemi, ma penso che la soluzione sia pericolosa,

ho eseguito lo script 3 volte, terminando il for dopo 3500 loop

i dati sottostanti riportano il risultato dei 3 run,
come si vede, i primi 2 sono terminati comunque con un numero ragionevole di random generati (accessi sul db)
il terzo run non ha completato il lavoro e non ha scritto tutti i record attesi (9000) nel db
PHP:
prima esecuzione, record nel db 3502, random generati 4427

[07-Aug-2017 14:21:45 Europe/Rome] 1000 - 1 - 0.0030548572540283 - somma 1
[07-Aug-2017 14:22:03 Europe/Rome] 4501 - 1 - 0.0048789978027344 - somma 4427

seconda esecuzione, record nel db 7004, random generati 9526

[07-Aug-2017 14:24:48 Europe/Rome] 1000 - 1 - 0.0057899951934814 - somma 1
[07-Aug-2017 14:25:53 Europe/Rome] 4501 - 6 - 0.042262077331543  - somma 9526

terza esecuzione, record nel db 8963, random generati 38234

[07-Aug-2017 14:30:02 Europe/Rome] 1000 - 11  - 0.12293195724487 - somma 11
[07-Aug-2017 14:34:59 Europe/Rome] 2958 - 251 - 1.9480979442596  - somma 38234
[07-Aug-2017 14:35:02 Europe/Rome] PHP Fatal error:  Maximum execution time of 300 seconds exceeded

questo risultato mi fa pensare che con l'esaurimento progressivo del range, i tempi possano aumentare a dismisura

si potrebbe pensare ad una soluzione alternativa che prevede

- creare una tabella nel db con i numeri (1000-9999) predisposti nella sequenza casuale (eseguita una sola volta)

- leggere il primo record della tabella per usarlo, quando serve
- cancellare il record usato

e via a seguire,
tempi certi, senza attese, risultato identico
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.042
149
63
PR
www.borgo-italia.it
ciao
forse è una schifezza, ma così faccio una sola query di interrogazione per trovare il CodiceCliente esistente o no
PHP:
function genera_code(){
    return 'CC-'.rand(1000,9999);
}
//......
$q=mysqli_query($connessione,"SELECT CodiceCliente FROM clienti");
while($riga=mysqli_fetch_assoc($q)){
    $esiste[]=$riga['CodiceCliente'];
}
$code=genera_code();
while(in_array($code, $esiste)){
    $code=genera_code();
}
$query = mysqli_query($connessione,"INSERT INTO clienti (NomeAzienda, CodiceCliente) VALUES ('$nome_azienda', '$code')");
//...
comunque non l'ho provata
 

marino51

Utente Attivo
28 Feb 2013
3.041
192
63
Lombardia
ma così faccio una sola query di interrogazione
si ma ogni volta che ti serve un numero, leggi l'intera tabella "SELECT CodiceCliente FROM clienti"
trasformando la "tabella" in "array" (non in questo caso ma una limitazione per grandi quantità)
potresti provare il mio stesso esercizio nel post 9
https://forum.mrw.it/threads/php-4-numeri-casuale-no-doppioni.49359/#post-193023
e confrontarlo con la proposta,
- creare una tabella nel db con i numeri (1000-9999) predisposti nella sequenza casuale
(operazione eseguita una sola volta, no limiti)
- leggere il primo record della tabella per usarlo, quando serve
- cancellare il record usato
 
  • Like
Reactions: bubino8

bubino8

Utente Attivo
28 Apr 2017
360
20
28
29
BZ
- creare una tabella nel db con i numeri (1000-9999) predisposti nella sequenza casuale
(operazione eseguita una sola volta, no limiti)
- leggere il primo record della tabella per usarlo, quando serve
- cancellare il record usato

Buona idea la terrò presente
 
Discussioni simili
Autore Titolo Forum Risposte Data
G Generazione di numeri random in PHP PHP 5
G Operazioni matematiche con grandi numeri PHP PHP 5
A [PHP] Script con array con numeri che iniziano per 00 PHP 2
M [PHP] Controllo campo cap con trattino oltre ai numeri PHP 3
M [PHP] range tra due numeri PHP 7
T [PHP] ordinare un campo varchar che contiene numeri PHP 6
filippino Riconoscere numeri pari e dispari con PHP PHP 1
T numeri casuali in php PHP 12
I dominio aruba versione php server linux Domini 1
G Colorare menu select attraverso ricerca php PHP 0
L PHP motore di ricerca nel sito PHP 1
S PHP e Mysqli PHP 0
Y Stampare da php su un foglio A6 attraverso una stampante esterna PHP 1
M Visulizzare immagine con php PHP 8
G [PHP] Creare script di prenotazione con controllo disponibilità. PHP 7
G leggere file txt e stampare con php il contenuto a video PHP 7
F Ricreare struttura php+mysql su Xampp Apache 0
Z PHP.INI - STMP per invio email con PHP Server Dedicati e VPS 0
M Array associativi php su 2 campi mysql PHP 10
G Invio form con PHP PHP 3
T fatture con voci fattura in php PHP 0
T ALTRO PROBLEMA CON ARRAY PHP PHP 1
M Collegamento tra form html e script php PHP 4
M Problemi con la stampa dei valori in php PHP 1
W [Cerco collaborazioni] Sviluppatore Web (PHP) Offerte e Richieste di Lavoro e/o Collaborazione 1
D passare valori da database sql a php PHP 1
L Ricezione dei dati su file php da modulo html PHP 6
E Inviare variabile a PHP da ciclo in JS Javascript 0
A form PHP prenotazione tramite query PHP 2
A Form php prenotazione di un azienda sanitaria locale presso studio medico PHP 1
F menù select dinamico da db in php PHP 3
L Problemi form Pagina php HTML e CSS 3
L php mysql non salva solo id PHP 21
L php mysql cerca e visualizza pagina PHP 0
F Il codice php è giusto? PHP 2
R Aggiornare record mysql con Ajax, jQuery e php Ajax 2
A invio massivo dati a file php Javascript 4
Z MySql injection PHP PHP 1
V PHP form intersecate PHP 0
I [Offro][Retribuito] Programmatore Php Offerte e Richieste di Lavoro e/o Collaborazione 0
P Funzione jQuery Ajax invio file a php jQuery 1
C Dopo chiusura del tag php la stringa html va a capo PHP 1
E Transaction php PHP 11
B ciclare file xml con PHP PHP 1
L Estrazione dati php Database 6
A Aiuto per pagina php PHP 0
E Php select option e ajax PHP 23
I Aiuto php Dependent Lookup PHP 0
T arretramento versione PHP... PHP 3
D problema php mysql PHP 1

Discussioni simili