[PHP] 4 numeri casuale no doppioni

bubino8

Utente Attivo
28 Apr 2017
360
20
28
31
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
322
21
28
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.203
207
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.203
207
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
31
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.203
207
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.046
150
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.203
207
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
31
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
F Cerco Hosting con VECCHIE versioni di php Hosting 0
Cosina Captcha php PHP 1
S passare un valore da un form a un file .php con metodo post PHP 4
N php msyql PHP 6
N php problemi a visualizzare video PHP 3
A menu a tendina php PHP 1
D protezione cartelle: blocco visualizzazione/scaricamento contenuto, ma abilitazione utilizzo dati da parte di file .php presenti sul sito Web Server 1
F Php date_diff PHP 1
K [PHP] Aggiungere caratteri ad una stringa in base alla lunghezza della stessa PHP 2
C Wp-admin a file php WordPress 5
Lino80 [Retribuito] Cerco programmatore php per modifica/inserimento funzione/valori da un plugin importer wordpress Offerte e Richieste di Lavoro e/o Collaborazione 0
csi Inviare file jpg in locale alla stampante con php PHP 0
M Passaggio variabili array php su un tasto jq PHP 3
E Php aggiornamento tabella PHP 9
G phpmailer e php 8.1 con estensione mysqli PHP 6
M Invio dati database via email php PHP 0
K [php] Problema con inner join PHP 4
K [php]form invio dati PHP 0
P Codifica caratteri speciali mysql php PHP 0
K [PHP] Problema con variabili concatenate. PHP 1
E Stampante termica escpos-php PHP 6
JeiMax Modifica codice php personalizzato PHP 2
G Come modificare un pdf in php PHP 1
U Link a doppio file PHP PHP 0
E PHP & jQuery PHP 8
N Passare array da php a javascript PHP 5
F Applicazione PHP/MySQL per prenotazioni: limitare il numero massimo di posti prenotabili PHP 20
L tipo boolean non funzionante su mariadb (mysql). E codice php 7.4. PHP 0
U PHP creare un file excel dopo ricerca nel DB PHP 0
M PHP/MySQL - Estrarre valori min e max di ogni gruppo PHP 5
F Php e fatturazione elettronica PHP 0
P lanciare script asp (o php) da jquery Javascript 1
Couting95 inserire dati da un file di testo in una tabella in php PHP 1
P Data scraping in PHP non funziona PHP 4
C Calcoli matematici in php PHP 5
F Scrivere dei dati in word con php PHP 0
D PHP leggere cartella di Windows PHP 1
I dominio aruba versione php server linux Domini 3
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

Discussioni simili