errore con mysql insert in PDO

Discussione in 'PHP' iniziata da 3_g, 9 Ottobre 2018.

  1. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    devo leggere un file di testo (delimitato) e inserire le righe nei campi di un DB... e non ci sarebbe niente di strano se non fosse che la query se inserita in mysql... funziona, inserita in uno script php...no:(
    il file da leggere è questo:
    101|0|"Nome Cognome"|"Citta"|1|0|0|0.0|0|0|0.0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1

    sono in tutto 28 valori di diverso tipo, principalmente integer poi float e testo
    PHP:
    $camp=23;
    $textarray=file("file.txt");

    for(
    $i=0$i<count($textarray); $i++)
    {
      
    $text=substr($textarray[$i],0,-1);

      list(
    $var1,$var2,$var3,$var4,$var5,$var6,$var7,$var8,$var9,$var10)=explode('|',$text);

      
    $database->query('INSERT INTO Tabella VALUES (
      \'\',
      :camp,
      :var1,
      :var2,
      :var3,
      :var4,
      :var5,
      :var6,
      :var9,
      :var10)'
    );

    //  $database->bind(':id', 100);
      
    $database->bind(':camp'$camp);
      
    $database->bind(':var1'$var1);
      
    $database->bind(':var2'$var2);
      
    $database->bind(':var3'str_replace('"'''$var3));
      
    $database->bind(':var4'str_replace('"'''$var4));
      
    $database->bind(':var5'$var5);
      
    $database->bind(':var6'$var6);
      
    $database->bind(':var9'$var9);
      
    $database->bind(':var10'$var10);

      
    $database->execute();
    }
    questo l'errore:
    Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '' for column 'ID_Dati' at row 1

    questo è l'errore generato cercando di inserire un valore nullo per il campo autoicrementale


    PHP:
    $database->query('INSERT INTO TB_DatiGiornate VALUES (
      :id,
      :camp,
    .........
     $database->bind('
    :id', 100);
     $database->bind('
    :camp', $camp);
    ... questo cercando di inserire un valore nel campo autoincrementale:
    Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '100' for key 'PRIMARY'

    PHP:
      $database->query('INSERT INTO TB_DatiGiornate VALUES (
      :camp,
    ..............
      $database->bind('
    :camp', $camp);
    questo cercando di fare inserire automaticamente il valore del campo autoincrementale:
    Fatal error: Uncaught PDOException: SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 1


    PRECISAZIONI:
    - per semplicità ho importato solo i primi 10 valori del file di testo;
    - la tabella ha 2 ulteriori campi: ID_Dati (campo autoincrementale e camp che va valorizzato con la variabile $camp)
    - ho fatto le prove anche specificando la lista completa dei campi della tabella (con e senza il campo autoincrementale)
    Codice:
    INSERT INTO Tabella (ID_Dati, Camp, var1, var2, var3, var4, var5, var6, var9, var10) VALUES (':id', :camp, :var1, :var2, :var3, :var4, :var5, :var6, :var9, :var10)');
    
    oppure
    
    INSERT INTO Tabella (Camp, var1, var2, var3, var4, var5, var6, var9, var10) VALUES (':camp, :var1, :var2, :var3, :var4, :var5, :var6, :var9, :var10)');
     
    ...di prove ne ho fatte tante ma non ho trovato quella giusta... avete qualche idea?:rolleyes:
     
  2. macus_adi

    macus_adi Utente Attivo

    Registrato:
    5 Dicembre 2017
    Messaggi:
    556
    Mi Piace Ricevuti:
    26
    Punteggio:
    28
    Sesso:
    Maschio
    Occupazione:
    Developer
    Località:
    L'Aquila
    Solitamente l'autoincrement non si valorizza ma si lascia la gestione dello stesso al DBMS, infatti come vedi l'errore della seconda è
    ossia la chiave primaria è duplicata, in questo caso mi pare di capire che stai settando id=100 ma è già presente...

    Detto questo, per la prima parte:

    In questa porzione hai commesso errore di binding ossia nell'insert sono presenti 10 bind, ma tu ne passi solo 9...
    Potresti abbreviare la tua query utilizzando un ciclo il che sarebbe molto più comoda la gestione:

    PHP:

    $values
    =explode('|',$text);

    unset(
    $values[0]);//elimino ID autoincrementale

    $map_items=['camp','var1','var2','var3','var4','var5','var6','var7','var8','var9','var10'];
    $compile_items=[];
    //in questo modo mappi automaticamente i dati attraverso un'array associativo, per effettuare il bind
    $query='INSERT INTO Tabella';
    $type='';
    $inter_=[];
    foreach(
    $map_items as $k=>$v){
    $compile_items[$v]=$values[$k+1];
    //non è lo scopo corretto lo inserisco solo a scopo illustrativo, dovrebbe essere processato da un QB apposito e no da iterazione
    $inter_[]='?';
    switch(
    $k){
     
    //da implementare la tipologia per il binding
    /*sarebbe utili reperire la tipologia dei dati sul db in modo automatico passando la tipologia creando un querybuilder o utilizzandone uno già pronto*/
        
    default:$type.='i';
    }
    }
    //in questo modo la nostra query si costruisce in automatico
    $query.='('.join(',',array_keys($compile_items)).') VALUES ('.join(',',$inter_)).')';

    $this->conn->execute_stmt($query,$compile_items,$type)->result;
    Per effettuare il binding qua ci sta un metodo:
    https://forum.mrwebmaster.it/threads/php-ricerca-record-tramite-post.52470/#post-204377


    Potresti pensare di utilizzare qualche lib o framework di supporto per la gestione e lavorazione dei dati.. medoo.in (https://medoo.in/) non è affatto male.
     
  3. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    ma la prova lasciando che il campo si valorizzasse da solo l'ho fatta (non ho riportato l'errore:() ma non funziona lo stesso
    INSERT INTO Tabella (Camp, var1, var2, var3, var4, var5, var6, var9, var10) VALUES (':camp, :var1, :var2, :var3, :var4, :var5, :var6, :var9, :var10)');
    questa sera la faccio "girare" e riporto l'errore

    il valore '100' non è presente (la tabella ha 1 solo record registrato) l'ho inserito di proposito per "vedere" cosa succedeva...

    non ho ancora padronanza del PHP per cui cerco di fare le cose semplici... e non mi riescono neanche quelle:(:(
    il tuo codice e molto più efficiente ma vorrei aspettare di implementarlo per capire prima dove è l'errore nella mia query;)

    nel 1 caso il binding corrisponde (9 su 9) il primo valore \'\' è per passare un valore nullo al campo autoincrementale per far si che sia il DBMS a metterlo... ho fatto la prova anche togliendo questo "valore" e lasciando solo i 9 binding...
    diciamo che di prove/combinazioni (anche ad minchiam:eek:) ne ho fatte tante... perchè finite le soluzioni "logiche" per me... ho iniziato ad andare nel pallone:D
     
  4. macus_adi

    macus_adi Utente Attivo

    Registrato:
    5 Dicembre 2017
    Messaggi:
    556
    Mi Piace Ricevuti:
    26
    Punteggio:
    28
    Sesso:
    Maschio
    Occupazione:
    Developer
    Località:
    L'Aquila
    in realtà no, l'autoincrement non dovrebbe essere passato.

    Prova a creare una tabella senza autoincrement e senza vincoli vedi cosa succede.... se i dati vengono inseriti è come ti dico io....
     
  5. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    ok, questa sera ci provo (ora sono a lavoro:))... poi ti aggiorno;)
     
  6. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    può essere utile prima di provare, leggere
    http://www.mysqltutorial.org/mysql-null/
    guarda la tabella di esempio e come scrive la insert

    con i geroglifici spesso ci si perde ….
    al posto di scrivere /'/'
    quando ne avessi necessità, potresti scrivere un bel NULL
     
  7. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    già provato;)
    rimane il fatto che la query inserita in mysql funziona... messa con il PDO/binding... no

    forse ci sono dei parametri da tener conto in base a come è fatta la tabella... stasera vi posto la struttura... precisa:)
     
  8. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    mi è venuto un dubbio... nella classe che uso (presa su interneto_O) la funzione bind è fatta così:
    PHP:
        // funzione bind
        
    public function bind($param$value$type null) {
            if (
    is_null($type)) {
                switch (
    true) {
                    case 
    is_int($value):
                        
    $type PDO::PARAM_INT;
                        break;
                    case 
    is_bool($value):
                        
    $type PDO::PARAM_BOOL;
                        break;
                    case 
    is_null($value):
                        
    $type PDO::PARAM_NULL;
                        break;
                    default:
                        
    $type PDO::PARAM_STR;
                }
            }
            
    $this->stmt->bindValue($param$value$type);
        }
    il problema di inserimento può derivare da questa??
     
  9. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    prove in diretta:eek:...
    struttura delle tabelle del db:
    PHP:
    CREATE TABLE `Tabella1` (
      `
    ID_Datiint(11NOT NULL AUTO_INCREMENT PRIMARY KEY,
      `
    Campint(11NOT NULL,
      `
    field1tinyint(4) DEFAULT NULL,
      `
    field2varchar(100) DEFAULT NULL,
      `
    field3varchar(20) DEFAULT NULL,
      `
    field4tinyint(4) DEFAULT NULL,
      `
    field5float DEFAULT NULL,
      `
    field6tinyint(4) DEFAULT NULL,
      `
    field7int(11) DEFAULT NULL
    ENGINE=InnoDB;

    CREATE TABLE `Tabella2` (
      `
    Campint(11NOT NULL,
      `
    field1tinyint(4) DEFAULT NULL,
      `
    field2varchar(100) DEFAULT NULL,
      `
    field3varchar(20) DEFAULT NULL,
      `
    field4tinyint(4) DEFAULT NULL,
      `
    field5float DEFAULT NULL,
      `
    field6tinyint(4) DEFAULT NULL,
      `
    field7int(11) DEFAULT NULL
    ENGINE=InnoDB;
    dati da inserire (file.txt):
    Codice:
    101|"Nome Cognome"|"citta"|1|0.0|5|1
    102|"Nome Cognome"|"citta"|2|0.1|4|1
    103|"Nome Cognome"|"citta"|3|0.2|3|1
    104|"Nome Cognome"|"citta"|4|0.3|2|1
    105|"Nome Cognome"|"citta"|5|0.4|1|1
    codice "fisso" dello script (la parentesi graffa di chiusura del for è riportata alla fine dello script:
    PHP:
    $database = new Database($db$u$p);

    $camp=23;
    $textarray=file("file.txt");

    for(
    $i=0$i<count($textarray); $i++)
    {
      
    $text=substr($textarray[$i],0,-1);

      list(
    $var1,$var2,$var3,$var4,$var5,$var6,$var7)=explode('|',$text);
    1^ prova effettuata con questa query:
    PHP:
      $database->query('INSERT INTO Tabella1 VALUES (:camp, :var1, :var2, :var3, :var4, :var5, :var6, :var7)');

      
    $database->bind(':camp'$camp);
      
    $database->bind(':var1'$var1);
      
    $database->bind(':var2'str_replace('"'''$var2));
      
    $database->bind(':var3'str_replace('"'''$var3));
      
    $database->bind(':var4'$var4);
      
    $database->bind(':var5'$var5);
      
    $database->bind(':var6'$var6);
      
    $database->bind(':var7'$var7);

      
    $database->execute();
    errore generato:
    Fatal error: Uncaught PDOException: SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 1
     
  10. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    2^ prova effettuata con questa query:
    PHP:
      $database->query('INSERT INTO Tabella2 VALUES (:camp, :var1, :var2, :var3, :var4, :var5, :var6, :var7)');
     
      
    $database->bind(':camp'$camp);
      
    $database->bind(':var1'$var1);
      
    $database->bind(':var2'str_replace('"'''$var2));
      
    $database->bind(':var3'str_replace('"'''$var3));
      
    $database->bind(':var4'$var4);
      
    $database->bind(':var5'$var5);
      
    $database->bind(':var6'$var6);
      
    $database->bind(':var7'$var7);

      
    $database->execute();
    FUNZIONA:)
     
  11. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    3^ prova effettuata con questa query:
    PHP:
      $database->query('INSERT INTO Tabella1 (ID_Dati, Camp, field1, field2, field3, field4, field5, field6, field7) VALUES ('', :camp, :var1, :var2, :var3, :var4, :var5, :var6, :var7)');

      
    $database->bind(':camp'$camp);
      
    $database->bind(':var1'$var1);
      
    $database->bind(':var2'str_replace('"'''$var2));
      
    $database->bind(':var3'str_replace('"'''$var3));
      
    $database->bind(':var4'$var4);
      
    $database->bind(':var5'$var5);
      
    $database->bind(':var6'$var6);
      
    $database->bind(':var7'$var7);

      
    $database->execute();
    errore generato:
    Parse error: syntax error, unexpected '', :camp, :var1, :var2, :var3,' (T_CONSTANT_ENCAPSED_STRING), expecting ',' or ')'
     
  12. 3_g

    3_g Nuovo Utente

    Registrato:
    5 Settembre 2017
    Messaggi:
    36
    Mi Piace Ricevuti:
    1
    Punteggio:
    8
    Sesso:
    Maschio
    Località:
    Ancona
    4^ prova effettuata con questa query:
    PHP:
      $database->query('INSERT INTO Tabella1 (Camp, field1, field2, field3, field4, field5, field6, field7) VALUES (:camp, :var1, :var2, :var3, :var4, :var5, :var6, :var7)');

      
    $database->bind(':camp'$camp);
      
    $database->bind(':var1'$var1);
      
    $database->bind(':var2'str_replace('"'''$var2));
      
    $database->bind(':var3'str_replace('"'''$var3));
      
    $database->bind(':var4'$var4);
      
    $database->bind(':var5'$var5);
      
    $database->bind(':var6'$var6);
      
    $database->bind(':var7'$var7);

      
    $database->execute();
    FUNZIONA CON QUESTA STRUTTURA DI DATI;);)... semplificata per fare le prove... ma con i dati "veri" no:confused::confused:

    la caccia continua:D:D:D
     
  13. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    dovresti rifare la prova scrivendo bene la query,
    considera anche la differenza tra virgolette e apici ….
    Codice:
    $database->query("
    INSERT INTO Tabella1
    (Camp, field1, field2, field3, field4, field5, field6, field7)
    VALUES
    (:camp, :var1, :var2, :var3, :var4, :var5, :var6, :var7)
    ");
    se non indichi i campi della tabella, come nel tuo esempio, il motore del db potrebbe "confondersi" perché ha un campo in più, l'autoincrement
     
    Ultima modifica: 10 Ottobre 2018
  14. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    certo che funziona, le colonne del db corrispondono alla tua query, puoi omettere l'elenco …..
    (salvo rispettare le clausole NOT NULL qualora ci fossero)
     
  15. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    c'è incongruenza tra apici, usa virgolette per delimitare la query e gli apici per i valori interni ad essa,
    vedi suggerimento prova 1
     
    Ultima modifica: 10 Ottobre 2018
  16. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    vedi quanto detto per la prova3, poi se puoi posta la query definitiva

    ps, nei miei sviluppi le query sono sempre complete, lista delle colonne e conseguenti valori, vedi suggerimento prova 1
    in questo modo, se qualcuno facesse variazioni al db, che dovesso renderlo incongruente rispetto all'applicazione,
    verrebbe segnalato un errore nell'esecuzione della query
    sono contrario a creare automatismi per associare dati a colonne,
    solito esempio estremo,
    se dalla tabella fatture venisse eliminata la colonna iva, per sbaglio, l'automatismo garantirebbe il funzionamento dell'applicazione,
    ma sai cosa significa perdere la colonna iva, senza che nessuno se ne accorge?

    quindi sviluppa in modo "sicuro", garantendo sempre il risultato ….
     
  17. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    da buon ultimo,
    mi sono creato miei metodi "estendendo" la classe PDO
    preferisco usare il posizionale "?" invece dell'associazione come fai tu
    questa è uno dei miei metodi,
    PHP:
      private function BindParams($sql$params)
      {
        if(
    $this->AllowLog$this->MyLog($this->pdoSqlDebug($sql$params));

        if (
    substr_count($sql"?") != count($params))
          
    $this->MyErr("PDO : incongruenza nei parametri della query -> ".$sql);

        
    $params $this->FixSQL($params);

        try { 
    $sth $this->pdo->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
              
    $sth->execute($params);
              return 
    $sth; }
        catch(
    PDOException $e){ $this->handle_sql_errors($sql$e$params); }
      } 
    quando le tue query funzionano, prova ad inserire come nome "D'Alessandro" e vedi che succede
    poi pensa a "FixSQL" che leggi nel mio codice
     
  18. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    questo metodo aggiunge il tipo del dato,
    dovresti aggiungere gli eventuali che mancano, mi sembra tu abbia float e forse altro
     
  19. macus_adi

    macus_adi Utente Attivo

    Registrato:
    5 Dicembre 2017
    Messaggi:
    556
    Mi Piace Ricevuti:
    26
    Punteggio:
    28
    Sesso:
    Maschio
    Occupazione:
    Developer
    Località:
    L'Aquila
    Per quanto riguarda la tipologia di dato appoggiati alla tabella information schema, senza andare lontano potresti utilizzare librerie di terze parti vedi medoo.in che ha tutti i metodi scritti abbastanza bene ampiamente documentato facilmente estensibile...
    Giusto per conoscenza, potresti utilizzare Eloquent di Laravel, che di tutta la diatribia scritta non ne vedrai neanche l'ombra, una semplice Eloquent::Insert($dati);
    ;)
     
  20. marino51

    marino51 Utente Attivo

    Registrato:
    28 Febbraio 2013
    Messaggi:
    2.271
    Mi Piace Ricevuti:
    114
    Punteggio:
    63
    Occupazione:
    free lance
    Località:
    Lombardia
    ma con pochi metodi ben scritti, estendendo la classe pdo, puoi ottenere lo stesso risultato, esempio
    PHP:
    public function queryM($sql$params=array())  // return the number of the involved rows (insert, update, delete)
    {
        return 
    $this->BindParams($sql$params)->rowCount();
    }


    $dbresult $db->queryM($sql, array($car['cod'], $car['descr'], $car['um'], $car['sort'], $car['aggior'], $car['nr']));
    ed hai "in mano" il tuo codice che rendi più funzionale alle tue necessità

    eloquente, no ?
     
    Ultima modifica: 10 Ottobre 2018
Sto caricando...

Condividi questa Pagina