VB
Sept. 16, 2020, 6:23 p.m.

QSqlTableModel не удаётся редактировать и удалять данные

SQLite, QT

Добрый день.

Впервые решил использовать для создания базы данных связку модели и представления. За основу взял SQLite. Класс Model унаследован от QSqlTableModel. Способ подключения базы данных и связки модели с представлением взял с этого сайта, немного изменив. Но, к сожалению, не работает обновление данных и удаление. Чтобы я ни делал, не получается. Может кто-нибудь знает решение?

Вот этот метод работает:

  1. bool Model::save_to_db(Data *item)
  2. {
  3. QSqlQuery query;
  4. query.setForwardOnly(true);
  5.  
  6. query.prepare("INSERT INTO myDB (code, date, person, description)"
  7. "VALUES (:code, :date, :person, :description)");
  8.  
  9. query.bindValue(":code", item->Code());
  10. query.bindValue(":date", item->Date());
  11. query.bindValue(":person", item->Person());
  12. query.bindValue(":description", item->Description());
  13.  
  14. if(query.exec()) return true;
  15.  
  16. qCritical() << query.lastError().databaseText();
  17. qCritical() << query.lastError().driverText();
  18. qCritical() << query.lastError().nativeErrorCode();
  19.  
  20. return false;
  21. }

Вот этот не работает (данные добавляются в представление, но не в базу):

  1. bool Model::update_in_db(Data *item)
  2. {
  3. QSqlQuery query;
  4. query.setForwardOnly(true);
  5. query.prepare("UPDATE myDB SET \n"
  6. " code = :code, \n"
  7. " date = :date, \n"
  8. " person = :person, \n"
  9. " description = :description \n"
  10. "WHERE id = :id; \n"
  11. );
  12.  
  13. query.bindValue(":code", item->Code());
  14. query.bindValue(":date", item->Date());
  15. query.bindValue(":person", item->Person());
  16. query.bindValue(":description", item->Description());
  17.  
  18. if(query.exec()) {
  19. return true;
  20. } else {
  21. qCritical() << query.lastError().databaseText();
  22. qCritical() << query.lastError().driverText();
  23. qCritical() << query.lastError().nativeErrorCode();
  24.  
  25. return false;
  26. }
  27. }

И удаление не работает:

  1. Model::delete_from_db()
  2. {
  3. QSqlQuery query;
  4. query.setForwardOnly(true);
  5. query.prepare("DELETE FROM myDB WHERE id = :ID ;");
  6. query.bindValue(":ID", currentIndex.row());//индекс сигналом по клику
  7. //передаю из MainWindow, так как представление находится в классе MainWindow
  8.  
  9. if(!query.exec()){
  10. qCritical() << query.lastError().databaseText().toUtf8().data();
  11. qCritical() << query.lastError().driverText();
  12. qCritical() << query.lastError().nativeErrorCode();
  13. return false;
  14. } else {
  15. return true;
  16. }
  17. return false;
  18. }

Исходный код

Спасибо за внимание!

3

Do you like it? Share on social networks!

5
Evgenii Legotckoi
  • Sept. 17, 2020, 12:20 p.m.
  • The answer was marked as a solution.

Добрый день.

Метод update_in_db скорее всего не работает из-за наличия знаков каретки \n , а также из-за того, что нет bind для ID.

Что касается delete_from_db , то тут я не уверен, в чём может быть ошибка. Что вываливается в вывод qCritical?

    VB
    • Sept. 17, 2020, 2:38 p.m.
    • (edited)

    Да, редактирование теперь работает! Спасибо!
    По поводу удаления, причина в том, что индекс в представлении отличается от id в базе. Нужно брать id для удаления из базы, а не из представления. Всё, задача решена!

      Evgenii Legotckoi
      • Sept. 17, 2020, 2:43 p.m.

      Если через раз, то дело скорее всего в том, что обычно ID является автоинкрементируемым столбцом, который всегда растёт, даже если какие-то строки удалялись из базы данных. Если у вас было 4 записи с ID: 1, 2, 3, 4 и вы удалили 4-й, то следующий ID будет 5 и в таблице будут 1, 2, 3, 5.

      В данном случае currentIndex.row() не отвечает ID, это просто номер строки в таблице. Вам нужно сначала получить ID записи, можно это сделать через метод data, просто нужно иметь столбки с ID, можно сделать его скрытым. А потом уже делать удаление по этому id

        VB
        • Oct. 30, 2020, 6:01 p.m.

        А удаление всё же не работает. Понял это когда по аналогии с этим проектом создал проект с картинками. При удалении элементов размер базы данных не меняется. То есть в представлении элемент показываться не будет, но из базы данных по видимому не удаляется.

          Алексей Внуков
          • Oct. 30, 2020, 6:56 p.m.
          • (edited)

          а проверить просто что находится в базе? и вообще SQLite, на сколько помню, удаляет данные из поля, чтоб изменить размер и удалить пустые строки нужно доболнительно делать вакуум

            Comments

            Only authorized users can post comments.
            Please, Log in or Sign up
            • Last comments
            • AK
              April 1, 2025, 11:41 a.m.
              Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
            • Evgenii Legotckoi
              March 9, 2025, 9:02 p.m.
              К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
            • VP
              March 9, 2025, 4:14 p.m.
              Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
            • ИМ
              Nov. 22, 2024, 9:51 p.m.
              Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
            • Evgenii Legotckoi
              Oct. 31, 2024, 11:37 p.m.
              Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup