Obsługa bazy danych SQLite konstrukcja zapytania

0

Witam,
uczę się od niedawna Qt oraz obsługi bazy danych. Pracuję na SQLite.

Staram się z 2 tabel pobrać WSPÓLNE wartości. Niestety nie mogę wczytać 1 rekordu.

QSqlQuery* pobierz_wsp = new QSqlQuery(mydb);
QString wspolne  = "SELECT '"+chem_id+"' FROM chem_propert INTERSECT SELECT chem_in FROM mag1" ;

if(!pobierz_wsp->exec(wspolne)){
                 qDebug()<<pobierz_wsp->lastQuery();
                 qDebug()<<pobierz_wsp->lastError().text();
             }	else {
                 while(pobierz_wsp->next()){
                     czyWsp = pobierz_wsp->value(0).toString();
                 }
                 ui->textDisplay->setText(czyWsp);
                 qDebug()<<pobierz_wsp->at();   // zwraca wartość -2
                 qDebug()<<pobierz_wsp->lastQuery();
                 qDebug()<<pobierz_wsp->size();  //zwraca wartość -1
                 qDebug()<<pobierz_wsp->value(0).toString(); //zwraca ""
            }
 

W SQLite zapytanie wykonuje się prawidłowo. user image
Dziękuję za każdą odpowiedź i pomoc - już nie mam zielonego pojęcia co jest nie tak.... ;/ Pozdrawiam.

0
std::string ghi;
QSqlQuery query(mydb);
query.prepare("SELECT abc FROM def WHERE ghi = :ghi);
query.bindValue(":ghi", QString::fromStdString(ghi));
// execute query

musisz się bronić przed SQL injection, chyba jak w Qt klikniesz F1 na QSqlQuery to będziesz miał długi manual jak się buduje kwerendy w Qt

0

Zdaję sobie sprawę ze sql injection i potrzebą zabezpieczenia, natomiast czy to jest powodem problemu z wykonaniem zapytania? U mnie po select występuje zmienna, którą chcę przekazać do zapytania - swoją drogą zmienna ta jest pobierana z comboboxa i nie wiem czy w ogóle dopuszczalne jest takie konstruowanie zapytania??

0

jeżeli jest to zahardcorowana zmienna (jest w combo boxie) to napisz funkcję, która wysyła zapytania dla tej wartości combo boxa i już, bo co parametryzować coś co jest stałe

bindValue samo Ci doda '' lub nie w zależności od typu, który bindujesz do placeholdera.

0

Jeśli Ci się chce to bardzo proszę o jakiś przykład, ciągle się ucze i troche ciężko mi to ogarnąc... ;/
Nie wychodzi mi bindowanie wartości.

Kod:

 
  pobierz_wsp->prepare("SELECT :chem_id FROM chem_propert INTERSECT SELECT chem_in FROM mag1") ;
  pobierz_wsp->bindValue(":chem_id", chem_id));

qDebug zwraca "SELECT :chem_id FROM chem_propert INTERSECT SELECT chem_in FROM mag1", czyli źle zbindowana wartość....

Wartość z comboboxa pobieram po nastąpieniu zdarzenia - wciśnięcie przycisku - na zasadzie: QString chem_id = ui->comboBox->currentText();

0

jeżeli chem_id jest QStringiem to powinno być ok

czemu źle zbindowana?

zaloguj to co Ci odpowiada baza, a nie jak wygląda string QSqlQuery

0
gośćabc napisał(a):

czemu źle zbindowana?

A

qDebug()<<pobierz_wsp->lastQuery();

nie powinno mi zwrócić zapytania z podmienioną już wartością :chem_id?
Druga sprawa, że z tego co wiem jeśli

qDebug()<<pobierz_wsp->size();

zwróci -1 tzn, że kwerenda jest pusta/zapytanie źle się wykonało?

Może szerzej opiszę jakie są moje intencje względem comboBox'a + sqlQuery. Z comboBoxa wybieram ITEM (jako jego nazwa), ITEM posiada swoją charakterystykę (konkretnie, czy może zostać zapisany w tabeli razem z innym ITEMem). Aby sprawdzić czy moge zapisać ITEM w tabeli, pobieram jego charakterystykę i przy użyciu INTERSECT porównuję charakterystykę z zawartością tabeli - jako wynik zapytania powinienem dostać kolumne ze wspólnymi wartościami. Czyli defacto jeśli kolumna nie jest pusta, to nie mogę wpisać ITEMu do tablicy. I o to mi chodzi, bo chcę wrzucać do tablicy (magazyn) itemy, takie które w swojej charakterystyce sie nie wykluczają. Ps. pod ITEM proszę sobie podstawić słowo "chemikalia/związek chemiczny" jako dobry przykład.

0

nie, tam nie ma automatycznej podmiany placeholdera na wartość, dzieje się to później

jakbyś miał to odpalone w konsoli to byś zobaczył może jakiś komunikat, incorrect syntax lub no connection

możliwe że wcale się nie połączyłeś z db;

a tu wystarczy

if(pobierz_wsp->next()){
    czyWsp = pobierz_wsp->value(0).toString();
}

edit:
wyprintuj last error
QSqlError::NoError 0 No error occurred.
QSqlError::ConnectionError 1 Connection error.
QSqlError::StatementError 2 SQL statement syntax error.
QSqlError::TransactionError 3 Transaction failed error.
QSqlError::UnknownError 4 Unknown error.

co Ci zwraca to qDebug()<<pobierz_wsp->lastError().text();

kwerendę masz wykonać tak -> bool result = pobierz_wsp->exec();

0

Baza jest połączona, bo na początku zdefiniowałem sobie

if(!mydb.open())
       ui->label_2->setText("Failed to open");				//if db cant be open setText ...
   else
       ui->label_2->setText("Connected!");	 

właśnie żeby mieć status bazy na oku.
Nie wiem czy srawdzenie co zwraca baza robi się tak:

qDebug()<<sprawdz_wsp->exec();

jeśli tak to, zwraca mi TRUE.

3 dzień się męczę z tym problemem i nijak nie widzę rozwiązania.... ;/ Czy problemem może być struktura tabeli o którą wypytuję ? user image

0
bool wynik = pobierz_wsp->exec();
qDebug()<<wynik
 

Zwraca TRUE.

 
qDebug()<<pobierz_wsp->lastError().text();

Zwraca jedynie " "

0

no to dobrze to znaczy, że się wykonało,

teraz wyprintuj if(pobierz_wsp->next()) { qDebug() << pobierz_wsp->value(0).toString(); }

mam nadzieję, że nazwa kolumny w bazie pokrywa się z nazwą w combo boxie (co do literki)

0

Nazwy są identyczne, zwracałem na to uwagę przy wpisywaniu.

 
if(pobierz_wsp->next()){
 qDebug()<<pobierz_wsp->value(0).toString();
}

Nie zwraca mi nic - w sensie, że warunek dla if zwrócił false.
Jaka może być tego przyczyna??? ;/

0

wyprintuj chem_id, które podajesz do kwerendy

tuż przed bindowaniem

0

Zwraca poprawną zawartość, np. "Inorganic Acids".

0

wklej całą funkcję

0
 
void MainWindow::on_pushButton_clicked()
{
  QString mag_id = ui->comboBox_2->currentText();  // stores which magazine has been chosen in the combobox
  QString chem_id = ui->comboBox->currentText();  // does the same as previous


  QSqlQuery* pobierz_wsp = new QSqlQuery(mydb);

  pobierz_wsp->prepare("SELECT :chem_id FROM chem_propert INTERSECT SELECT chem_in FROM mag1") ;
  qDebug()<<chem_id;
  pobierz_wsp->bindValue(":chem_id", chem_id);
  QString czyWsp;


  pobierz_wsp->exec();
  if(pobierz_wsp->next())
                     qDebug()<< pobierz_wsp->value(0).toString();                    
 else 
                     ui->textDisplay->setText("Nie wykonalo sie");

                 qDebug()<<pobierz_wsp->lastQuery();
                 bool wynik = pobierz_wsp->exec();
                 qDebug()<<wynik;
                 qDebug()<<pobierz_wsp->lastError().text();                 
0

ostatni test, zrób tak, że wklej całą gotową kwerendę do prepare i nic nie binduj (wklej to co wklejałeś tam do jakiegoś management studio i wykonaj w programie), nie czytaj nic z combo boxa, zahardcoduj odpisz czy działa, jak nie, tzn że błąd jest gdzieś indziej

edit ok chyba wiem co jest źle

ale najpierw zrób tak jak powiedziałem

0
pobierz_wsp->prepare(QString("SELECT %1 FROM chem_propert INTERSECT SELECT chem_in FROM mag1").arg(chem_id));

bez bindowania, bindujemy tylko wartości a nie kolumny, (mój błąd)

0
 
  QSqlQuery* pobierz_wsp = new QSqlQuery(mydb);
  pobierz_wsp->prepare("SELECT 'Inorganic Acids' FROM chem_propert INTERSECT SELECT chem_in FROM mag1") ;
  QString czyWsp;

                bool czynext = pobierz_wsp->exec();
                qDebug()<<"Czy wykonalo sie exec: "<< czynext;
                qDebug()<<"Ostatnia kwerenda: "<<pobierz_wsp->lastQuery();
                qDebug()<<"Ostatni error: "<<pobierz_wsp->lastError().text();

                 if(pobierz_wsp->next()){
                     qDebug()<<"Pobrana wartosc: "<<pobierz_wsp->value(0).toString();
                     czyWsp = pobierz_wsp->value(0).toString();

                 } else qDebug()<<"Nie udalo sie pobrac wartosci";
                qDebug()<<"czyWsp: "<<czyWsp;

Zwraca:

 
Czy wykonalo sie exec:  true
Ostatnia kwerenda:  "SELECT 'Inorganic Acids' FROM chem_propert INTERSECT SELECT chem_in FROM mag1"
Ostatni error:  " "
Nie udalo sie pobrac wartosci
czyWsp:  ""
0

przeczytaj mój ostatni post, aha i niespójna nazwa, zmień na inorganic_acids w combo i w tabeli

0
gośćabc napisał(a):

przeczytaj mój ostatni post, aha i niespójna nazwa, zmień na inorganic_acids w combo i w tabeli

Jesteś wielki! Działa pieknie :) Jeszcze raz bardzo dziękuje za pomoc!

1 użytkowników online, w tym zalogowanych: 0, gości: 1