[PHP] 4 numeri casuale no doppioni

bubino8

Utente Attivo
28 Apr 2017
344
19
18
28
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
255
11
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.001
173
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.001
173
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
344
19
18
28
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.001
173
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
148
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.001
173
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
344
19
18
28
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
L Problemi form Pagina php HTML e CSS 2
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
D problema php mysql PHP 1
E Barra di avanzamento codice PHP PHP 4
G creazione menu a tendina e invio a pagina php PHP 1
A inserire variabile php colore in div html PHP 2
Z Video protetto con PHP PHP 0
Z Problema di sincronizzazione PAYPAL con PHP PHP 1
I Eecuzione di javascript in ciclo foreach php. PHP 7
S Libreria PHP per creare file dwg o dxf PHP 0
A [cerco - retribuito] Sviluppatore Php freelance per progetti vari Offerte e Richieste di Lavoro e/o Collaborazione 2
L Google chart php mysql PHP 2
R Download file multipli da directory php PHP 0
F pagina dinamica PHP PHP 3
P Rimozione automatica url da sitemap.xml con PHP PHP 1
L php tinymce mi duplica la classe label PHP 3
S Errore PHP - Notice: Undefined index ... PHP 14
N file manager da php 5 a 7 PHP 15
M Utilizzare la funzione mysql_num_rows() in PHP 5 PHP 3
elpirata Update dinamico informazioni scritte in una pagina php jQuery 11
N Mysql_result per PHP 7 PHP 2
Emix Select concatenate php sql ajax PHP 2
P Modifica con PHP di un node in una sitemap xml PHP 0
D Come usare funzione php PHP 6
P Cancellazione specifici files in una folder php PHP 1

Discussioni simili