Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. Italian
  4. Problema con query e QSqlQuery prepare
Forum Updated to NodeBB v4.3 + New Features

Problema con query e QSqlQuery prepare

Scheduled Pinned Locked Moved Solved Italian
23 Posts 2 Posters 8.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    fermatqt
    wrote on last edited by
    #1

    ciao a tutti!
    ho questa query in un file di testo.
    se la eseguo dentro all'sqldeveloper funziona correttamente, mentre qui non estrae nulla:

    SELECT 
    LT.DESCR128 DESCRIZIONE,
    LT.NUMERAT || LT.PERIODO || LPAD(LT.NUM, 6, '0') || LT.SERIE LISTINO,
    MA.CODINT ARTICOLO,
    LD.PRZDIVISA PREZZO,
    LD.SCONTO1 SCONTO1,
    LD.SCONTO2 SCONTO2,
    LD.SCONTO3 SCONTO3,
    LT.DAL DAL,
    LT.AL AL 
    FROM LIST_OFF_DETT LD 
    INNER JOIN MAT_ANAG MA ON MA.NPAM = LD.NPAM 
    INNER JOIN LIST_OFF_TEST LT ON LT.NUMERAT = LD.NUMERAT AND LT.PERIODO = LD.PERIODO AND LT.NUM = LD.NUM AND LT.SERIE = LD.SERIE 
    WHERE 
    MA.DITMAT = 'XXL' AND MA.FVL =  ' ' 
    AND LT.DITTA = 'XXL' AND LT.FVL = ' ' 
    AND LD.DITTA = 'XXL' AND LD.FVL = ' ' 
    AND MA.CODINT = :articolo;
    

    questo il codice:

            if (db->isOpened()) {
                QFile queryFile(":/get_listini_articolo.txt");
                queryFile.open(QFile::ReadOnly | QFile::Text);
                QByteArray ba = queryFile.readAll();
                QString strQuery(QString::fromUtf8(ba));
                strQuery.replace("\n", "");
                QSqlQuery query;
                query.prepare(strQuery);
                query.bindValue(":articolo", this->articolo);
                query.exec();
                qDebug() << query.lastError().text();
                int rows = 0;
                while (query.next()) {
                    ui->tblArticoli->insertRow(ui->tblArticoli->rowCount());
                    for (int i = 0; i < header.size(); ++i) {
                        ui->tblArticoli->setItem(rows, i, new QTableWidgetItem(query.value(header.at(i)).toString()));
                    }
                    rows++;
                }
                query.clear();
            }
    

    se invece usassi il LIKE nella query, e mettessi il bindValue in questo modo, funzionerebbe:

    query.bindValue(":articolo", this->articolo + "%");
    

    sinceramente non capisco il perchè.
    c'è un modo per visualizzare la query completo di parametro passato alla prepare?
    oppure avete altre idee??

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      Prima di tutto quersto

      QByteArray ba = queryFile.readAll();
      QString strQuery(QString::fromUtf8(ba));
      

      e' un incubo se cambi encoding o modo di scriver il newline. usa:

      QString strQuery = QTextStream(&queryFile).readAll();
      

      Prova a non mettere il ; alla fine e vedi se va

      @fermatqt said in Problema con query e QSqlQuery prepare:

      c'è un modo per visualizzare la query

      http://doc.qt.io/qt-5/qsqlquery.html#lastQuery

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      0
      • F Offline
        F Offline
        fermatqt
        wrote on last edited by
        #3

        ciao!

        innanzitutto grazie per il suggerimento.
        ho fatto subito la modifica con QTextStream.

        ho levato il ; finale, ma non cmq non ci sono record
        ho messo questa riga:

                   query.exec();
        
                    qDebug() << query.lastQuery(
        

        il problema è che vedo questo:

        "SELECT LT.DESCR128 DESCRIZIONE,LT.NUMERAT || LT.PERIODO || LPAD(LT.NUM, 6, '0') || LT.SERIE LISTINO,MA.CODINT ARTICOLO,LD.PRZDIVISA PREZZO,LD.SCONTO1 SCONTO1,LD.SCONTO2 SCONTO2,LD.SCONTO3 SCONTO3,LT.DAL DAL,LT.AL AL FROM LIST_OFF_DETT LD INNER JOIN MAT_ANAG MA ON MA.NPAM = LD.NPAM INNER JOIN LIST_OFF_TEST LT ON LT.NUMERAT = LD.NUMERAT AND LT.PERIODO = LD.PERIODO AND LT.NUM = LD.NUM AND LT.SERIE = LD.SERIE WHERE MA.DITMAT = 'XXL' AND MA.FVL =  ' ' AND LT.DITTA = 'XXL' AND LT.FVL = ' ' AND LD.DITTA = 'XXL' AND LD.FVL = ' ' AND MA.CODINT = :articolo"
        

        in sostanza non vedo che valore gli arriva!

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          per vedere i parametri usa http://doc.qt.io/qt-5/qsqlquery.html#boundValues

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          0
          • F Offline
            F Offline
            fermatqt
            wrote on last edited by
            #5

            ok, allora mi sembra che il parametro arrivi:

             QMapIterator<QString, QVariant> i(query.boundValues());
                        while (i.hasNext()) {
                            i.next();
                            qDebug() << i.key().toUtf8().data() << ": " << i.value().toString().toUtf8().data() << endl;
                        }
            

            ho provato a mettere il parametro fisso così:

            query.bindValue(":articolo", "C165-000");
            

            ma non è cambiato nulla.
            ovviamente se modifico la query in questo modo, funziona:

            SELECT 
            LT.DESCR128 DESCRIZIONE,
            LT.NUMERAT || LT.PERIODO || LPAD(LT.NUM, 6, '0') || LT.SERIE LISTINO,
            MA.CODINT ARTICOLO,
            LD.PRZDIVISA PREZZO,
            LD.SCONTO1 SCONTO1,
            LD.SCONTO2 SCONTO2,
            LD.SCONTO3 SCONTO3,
            LT.DAL DAL,
            LT.AL AL 
            FROM LIST_OFF_DETT LD 
            INNER JOIN MAT_ANAG MA ON MA.NPAM = LD.NPAM 
            INNER JOIN LIST_OFF_TEST LT ON LT.NUMERAT = LD.NUMERAT AND LT.PERIODO = LD.PERIODO AND LT.NUM = LD.NUM AND LT.SERIE = LD.SERIE 
            WHERE 
            MA.DITMAT = 'XXL' AND MA.FVL =  ' ' 
            AND LT.DITTA = 'XXL' AND LT.FVL = ' ' 
            AND LD.DITTA = 'XXL' AND LD.FVL = ' ' 
            AND MA.CODINT = 'C165-000'
            

            quindi si comporta come se non gli arrivasse il parametro in sostanza!

            1 Reply Last reply
            0
            • VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by VRonin
              #6

              dopo che hai eseguito la query senza succasso, puoi chiamare qDebug() << query.lastError().text(); per vedere cosa succede?

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              1 Reply Last reply
              0
              • F Offline
                F Offline
                fermatqt
                wrote on last edited by
                #7

                ciao.

                ho modificato così:

                        if (db->isOpened()) {
                            QFile queryFile(":/get_listini_articolo.txt");
                            queryFile.open(QFile::ReadOnly | QFile::Text);
                            QString strQuery = QTextStream(&queryFile).readAll();
                            strQuery.replace("\n", "");
                            QSqlQuery query;
                            query.prepare(strQuery);
                            query.bindValue(":articolo", "C165-000");
                            query.exec();
                
                            QMapIterator<QString, QVariant> i(query.boundValues());
                            while (i.hasNext()) {
                                i.next();
                                qDebug() << i.key().toUtf8().data() << ": " << i.value().toString().toUtf8().data() << endl;
                            }
                
                            int rows = 0;
                            while (query.next()) {
                                ui->tblArticoli->insertRow(ui->tblArticoli->rowCount());
                                for (int i = 0; i < header.size(); ++i) {
                                    ui->tblArticoli->setItem(rows, i, new QTableWidgetItem(query.value(header.at(i)).toString()));
                                }
                                rows++;
                            }
                            query.clear();
                
                            qDebug() << query.lastError().text();
                        }
                

                come output mi esce questo:

                :articolo :  C165-000 
                
                " "
                

                in sostanza non mostra nessun errore.
                è come se gli arrivasse un parametro "sbagliato" e che non è in grado di leggere bene.
                solo se metto l'uguale nella query, non se metto il LIKE.

                1 Reply Last reply
                0
                • VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #8

                  3 cose,

                  1. prova a sostituire query.exec(); con if(!query.exec()) Q_ASSERT(false);
                  2. che tipo é MA.CODINT? int, nvarchar, etc.
                  3. controlla che, con un altro manager per DB riesci a vedere dati con quella query quando usi l'uguale

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  1 Reply Last reply
                  0
                  • F Offline
                    F Offline
                    fermatqt
                    wrote on last edited by
                    #9

                    ok, allora:

                    1. ho messo così, me in output non dice nulla; quindi la query dovrebbe essere eseguita:
                            if (db->isOpened()) {
                                QFile queryFile(":/get_listini_articolo.txt");
                                queryFile.open(QFile::ReadOnly | QFile::Text);
                                QString strQuery = QTextStream(&queryFile).readAll();
                                strQuery.replace("\n", "");
                                QSqlQuery query;
                                query.prepare(strQuery);
                                query.bindValue(":articol", "C165-000");
                                //query.exec();
                                if(!query.exec()) Q_ASSERT(false);
                    
                                /*QMapIterator<QString, QVariant> i(query.boundValues());
                                while (i.hasNext()) {
                                    i.next();
                                    qDebug() << i.key().toUtf8().data() << ": " << i.value().toString().toUtf8().data() << endl;
                                }
                                qDebug() << query.lastError().text();*/
                    
                                int rows = 0;
                                while (query.next()) {
                                    ui->tblArticoli->insertRow(ui->tblArticoli->rowCount());
                                    for (int i = 0; i < header.size(); ++i) {
                                        ui->tblArticoli->setItem(rows, i, new QTableWidgetItem(query.value(header.at(i)).toString()));
                                    }
                                    rows++;
                                }
                                query.clear();
                            }
                    
                    1. MA.CODINT è un VARCHAR; il db è ORACLE

                    2. se esguo la query su SQLDEVELOPER funziona correttamente; anzi, io le faccio sempre prima su SQLDEVELOPER in modo da scrivere query corrette ed evitare questi problemi; ed infatti è questo che mi lascia perplesso!

                    VRoninV 1 Reply Last reply
                    0
                    • VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by
                      #10

                      query.bindValue(":articol", "C165-000"); manca una o... typo?

                      Sono abbastanza a corto di idee su cosa possa andare male, l'ultimo tentativo che ti chiederei e' usare positional binding cioe' sostituire :articolo nella query con ? e usare query.bindValue(0, QStringLiteral("C165-000"));

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      1 Reply Last reply
                      0
                      • F Offline
                        F Offline
                        fermatqt
                        wrote on last edited by fermatqt
                        #11

                        articol era solo una prova...

                        cmq ho messo così:

                                    query.bindValue(0, QStringLiteral("C165-000"));
                                    if(!query.exec()) Q_ASSERT(false);
                        
                        

                        e messo il ? nella query.
                        ma non estrae nulla.

                        ti capisco, anche io sono a corto di idee!

                        1 Reply Last reply
                        0
                        • F Offline
                          F Offline
                          fermatqt
                          wrote on last edited by
                          #12

                          allora, ho fatto la prova del 9.
                          ho scritto la query direttamente nel codice e levato il prepare:

                          QString strQuery = "SELECT LT.DESCR128 DESCRIZIONE,LT.NUMERAT || LT.PERIODO || LPAD(LT.NUM, 6, '0') || LT.SERIE LISTINO,MA.CODINT ARTICOLO,LD.PRZDIVISA PREZZO,LD.SCONTO1 SCONTO1,LD.SCONTO2 SCONTO2,LD.SCONTO3 SCONTO3,LT.DAL DAL,LT.AL AL FROM LIST_OFF_DETT LD INNER JOIN MAT_ANAG MA ON MA.NPAM = LD.NPAM INNER JOIN LIST_OFF_TEST LT ON LT.NUMERAT = LD.NUMERAT AND LT.PERIODO = LD.PERIODO AND LT.NUM = LD.NUM AND LT.SERIE = LD.SERIE WHERE MA.DITMAT = 'XXL' AND MA.FVL =  ' ' AND LT.DITTA = 'XXL' AND LT.FVL = ' ' AND LD.DITTA = 'XXL' AND LD.FVL = ' ' AND MA.CODINT = '" + this->articolo + "'";
                          
                                      QSqlQuery query;
                                      query.exec(strQuery);
                          

                          così funziona, concatenando il singolo apice nella stringa del parametro.
                          potrebbe essere quello il problema???

                          1 Reply Last reply
                          0
                          • VRoninV Offline
                            VRoninV Offline
                            VRonin
                            wrote on last edited by
                            #13

                            purtroppo quella soluzione apre le porte dell'inferno chiamato SQL Injection quindi non e' accettabile.
                            prova a guardare cosa ti da in output:

                            qDebug() << db->driver->hasFeature(QSqlDriver::PreparedQueries);
                            qDebug() << db->driver->hasFeature(QSqlDriver::NamedPlaceholders);
                            qDebug() << db->driver->hasFeature(QSqlDriver::PositionalPlaceholders);
                            

                            se sono tutti true prova a usare bindValue con la query scritta nel codice e vedere se cosi' funziona

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            1 Reply Last reply
                            0
                            • F Offline
                              F Offline
                              fermatqt
                              wrote on last edited by
                              #14

                              si ma infatti è solo una prova.
                              non ho intenzione di usare la query così!

                              cmq QSqlDriver::NamedPlaceholders mi da false, gli altri true.
                              quindi suppongo debba sempre usare ? e non :articoli.
                              se così, ho provato in questo modo:

                                          QString strQuery = "SELECT LT.DESCR128 DESCRIZIONE,LT.NUMERAT || LT.PERIODO || LPAD(LT.NUM, 6, '0') || LT.SERIE LISTINO,MA.CODINT ARTICOLO,LD.PRZDIVISA PREZZO,LD.SCONTO1 SCONTO1,LD.SCONTO2 SCONTO2,LD.SCONTO3 SCONTO3,LT.DAL DAL,LT.AL AL FROM LIST_OFF_DETT LD INNER JOIN MAT_ANAG MA ON MA.NPAM = LD.NPAM INNER JOIN LIST_OFF_TEST LT ON LT.NUMERAT = LD.NUMERAT AND LT.PERIODO = LD.PERIODO AND LT.NUM = LD.NUM AND LT.SERIE = LD.SERIE WHERE MA.DITMAT = 'XXL' AND MA.FVL =  ' ' AND LT.DITTA = 'XXL' AND LT.FVL = ' ' AND LD.DITTA = 'XXL' AND LD.FVL = ' ' AND MA.CODINT = '?'";
                                          QSqlQuery query;
                                          query.prepare(strQuery);
                                          query.bindValue(0, this->articolo);
                                          query.exec();
                              

                              ma continuo ad avere zero record.

                              1 Reply Last reply
                              0
                              • VRoninV Offline
                                VRoninV Offline
                                VRonin
                                wrote on last edited by
                                #15

                                '?' questo e' sbagliato, non devi mettere gli apostrofi, solo il ?

                                @fermatqt said in Problema con query e QSqlQuery prepare:

                                quindi suppongo debba sempre usare ? e non :articoli.

                                corretto!

                                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                ~Napoleon Bonaparte

                                On a crusade to banish setIndexWidget() from the holy land of Qt

                                1 Reply Last reply
                                0
                                • F Offline
                                  F Offline
                                  fermatqt
                                  wrote on last edited by
                                  #16

                                  si quella con '?' era una prova.
                                  cmq ho provato sia così:

                                    QString strQuery = ".............. MA.CODINT = ?";
                                              QSqlQuery query;
                                              query.prepare(strQuery);
                                              query.addBindValue("C165-000");
                                  

                                  che così:

                                    QString strQuery = "........... MA.CODINT = ?";
                                              QSqlQuery query;
                                              query.prepare(strQuery);
                                              query.bindValue(0, this->articolo);
                                  

                                  non è che debba specificare di che tipo è il bindValue??

                                  1 Reply Last reply
                                  0
                                  • VRoninV Offline
                                    VRoninV Offline
                                    VRonin
                                    wrote on last edited by
                                    #17

                                    no, se this->articolo e' QString il tipo viene dedotto in automatico, devi specificare il tipo solo se vuoi passare l'equivalente di NULL

                                    proviamo con una query base:

                                    QSqlQuery query;
                                    query.prepare("select * from MAT_ANAG where CODINT = ?");
                                    query.bindValue(0, "C165-000");
                                    if(query.exec())
                                    {
                                    while(query.next()){
                                    qDebug() << query.record().value("CODINT");
                                    }
                                    }
                                    else{
                                    qDebug() << query.lastError().text();
                                    }
                                    

                                    e dimmi se ti da risultati

                                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                    ~Napoleon Bonaparte

                                    On a crusade to banish setIndexWidget() from the holy land of Qt

                                    1 Reply Last reply
                                    0
                                    • F Offline
                                      F Offline
                                      fermatqt
                                      wrote on last edited by
                                      #18

                                      ecco il codice:

                                          qDebug() << "STARTED";
                                          if (db->isOpened()) {
                                              QSqlQuery query;
                                              query.prepare("SELECT * FROM MAT_ANAG WHERE CODINT = ?");
                                              query.bindValue(0, "C165-000");
                                              if (query.exec()) {
                                                  while (query.next()) {
                                                      qDebug() << "CODINT: " << query.record().value("CODINT");
                                                  }
                                              } else {
                                                  qDebug() << query.lastError().text();
                                              }
                                          } else {
                                              qDebug() << "DB chiuso";
                                          }
                                          qDebug() << "FINISHED";
                                      

                                      una volta lanciato, il programma lavora per circa 5 secondi.
                                      quindi penso voglia dire che la query la sta eseguendo
                                      ma l'output è solo questo:

                                      STARTED
                                      FINISHED
                                      

                                      inoltre, se scrivessi una query appositamente errata (ad esempio SELEC e non SELECT) vedrei l'errore in console.
                                      quindi anche la query dovrebbe essere giusta.

                                      infine se uso il LIKE funziona:

                                          qDebug() << "STARTED";
                                          if (db->isOpened()) {
                                              QSqlQuery query;
                                              query.prepare("SELECT * FROM MAT_ANAG WHERE CODINT LIKE ?");
                                              query.bindValue(0, "C165-000%");
                                              if (query.exec()) {
                                                  while (query.next()) {
                                                      qDebug() << "CODINT: " << query.record().value("CODINT");
                                                  }
                                              } else {
                                                  qDebug() << query.lastError().text();
                                              }
                                          } else {
                                              qDebug() << "DB chiuso";
                                          }
                                          qDebug() << "FINISHED";
                                      
                                      1 Reply Last reply
                                      0
                                      • VRoninV Offline
                                        VRoninV Offline
                                        VRonin
                                        wrote on last edited by VRonin
                                        #19

                                        a questo punto sono convinto che il problema sia nei dati, non nella query.

                                        Prova una cosa. usa la query con il like ma sostituisci qDebug() << "CODINT: " << query.record().value("CODINT");
                                        con qDebug() << "CODINT: " << query.record().value("CODINT").toString().size(); se stampa 8 mi bevo un'intera bottiglia di vodka in un sol fiato!

                                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                        ~Napoleon Bonaparte

                                        On a crusade to banish setIndexWidget() from the holy land of Qt

                                        1 Reply Last reply
                                        0
                                        • F Offline
                                          F Offline
                                          fermatqt
                                          wrote on last edited by
                                          #20

                                          purtroppo niente vodka, ti avrei fatto volentieri compagni con il gin!

                                          questo il codice:

                                              qDebug() << "STARTED";
                                              if (db->isOpened()) {
                                                  QSqlQuery query;
                                                  query.prepare("SELECT * FROM MAT_ANAG WHERE CODINT LIKE ?");
                                                  query.bindValue(0, "C165-000%");
                                                  if (query.exec()) {
                                                      while (query.next()) {
                                                          qDebug() << "CODINT: " << query.record().value("CODINT").toString().size();
                                                      }
                                                  } else {
                                                      qDebug() << query.lastError().text();
                                                  }
                                              } else {
                                                  qDebug() << "DB chiuso";
                                              }
                                              qDebug() << "FINISHED";
                                          

                                          questo l'output:

                                          STARTED
                                          CODINT:  30
                                          CODINT:  30
                                          CODINT:  30
                                          CODINT:  30
                                          ....................
                                          FINISHED
                                          

                                          ho controllato sul db il tipo di campo:
                                          CODINT NOT NULL CHAR(30)

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved