M
May 16, 2017, 7:33 a.m.

Проверка наличия записи в БД при выполнении запроса

Qt, SQL

Есть программа в которой происходит добавление данных в базу SQL. Необходимо реализовать функцию проверки наличия записи при нажатии кнопки "Сохранить", если запись есть должен выполняться запрос Update, в ином случае выполняется запрос Insert. Как это реализовать?

2

Do you like it? Share on social networks!

27
Evgenii Legotckoi
  • May 16, 2017, 10:35 a.m.

Можно через QSqlQuery и логический оператор EXISTS сделать.

QSqlQuery query;
// Проверка наличия записей по дате
QString str = QString("SELECT EXISTS (SELECT * FROM TableExample WHERE Date = '%1');").arg("2017-08-03");
query.prepare(str);
query.exec();
query.next();

/* Если запись существует, то вызывается
 * информационное сообщение
 * */
if(query.value(0) != 0){
    QMessageBox::information(this, trUtf8("Error"), trUtf8("Record is exists"));
}
else
{
    // ToDo something
}

Также есть статья с проверкой наличия записей в базе данных

    M
    • May 16, 2017, 4:02 p.m.

    Вопрос: есть способ обновить модель QSqlQeuryModel?

      Evgenii Legotckoi
      • May 16, 2017, 8:09 p.m.

      Выполнить заново setQuery() с последней применённой QSqlQuery, с помощью метода query()

      model->setQuery(model->query());
        M
        • May 17, 2017, 7:14 a.m.

        если использовать model->setQuery(model->query().lastQuery()); ? я так понял что в данном случае он вызывает последний запрос

          Evgenii Legotckoi
          • May 17, 2017, 10:04 a.m.

          QSqlQuery всегда содержит только последний запрос, а lastQuery() возвращает этот запрос в виде строки QString, так что, если база данных используется одна, то разницы нет, в каком виде будет передаваться запрос в model->setQuery()

            M
            • May 17, 2017, 3:29 p.m.

            столкнулся с проблемой. приходиться на кнопку дважды нажимать чтоб выполнялся запуск кода приведенного вами. вызов произвожу через connect к данному слоту

              Evgenii Legotckoi
              • May 17, 2017, 3:56 p.m.

              Проблема в том, как вы применили код, который я вам привёл, а не в самом коде.

                M
                • May 17, 2017, 3:59 p.m.

                проблема как я выяснил в том что connect соединение с слотом с первого нажатия не производит. а подключается к слоту только со второго нажатия и запускает нормально слот. connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(tww())); вот так соединяю нажатие и слот

                  Evgenii Legotckoi
                  • May 17, 2017, 4:04 p.m.

                  Вы запихали connect не в то место в коде. Написали некачественный алгоритм, по которому коннект создаётся не в нужное время.

                    M
                    • May 18, 2017, 5:55 p.m.

                    Еще вопрос, с которым не могу разобраться. Есть ComboBox - raspsel, который позволяет выбрать поле из таблицы. Делаю я это следующим образом:

                     rasmd = new QSqlQueryModel(this);
                        QSqlQuery zrs;
                        zrs.exec("SELECT idr, CONCAT(rnumber, ' от ', rdata) FROM op");
                        rasmd->setQuery(zrs);
                        ui->raspsel->setModel(rasmd);
                        ui->raspsel->setModelColumn(1);
                    Теперь вопрос. Как сделать чтобы открыв форму для редактирования я видел выбранное значение и при этом мог поменять значение. через QDataWidgetMapper не получается правильно сделать. Не допонимаю как работает ComboBox
                      Evgenii Legotckoi
                      • May 18, 2017, 5:59 p.m.

                      Начнём с того, что QSqlQueryModel является моделью только для чтения, она не может быть редактируемой. А также, ответьте на вопрос. Зачем Вы выполняете метод exec() у QSqlQuery? Когда потом помещаете этот QSqlQuery в модель QSqlQueryModel? Обращение к базе данных происходит дважды.

                        M
                        • May 18, 2017, 6:04 p.m.

                        я так делаю потому что потом планирую сделать библиотеку sql запросов, потом исправлю, сейчас занимаюсь отладкой. Редактируемая же форма QSqlTableModel и QSqlRelationalTableModel. QSqlQueryModel я использую для извлечения данных из одной таблицы.

                          Evgenii Legotckoi
                          • May 18, 2017, 6:13 p.m.

                          Ну тогда у QComboBox есть методы currentData(), currentText(), currentIndex() с помощью которых можно забрать текущее значение. Передать его в сторону формы редактирования и с помощью этого значения выбрать нужную строку из таблицы базы данных, чтобы отобразить её в форме для редактирования.

                            M
                            • May 21, 2017, 7:11 p.m.

                            Опишу еще раз ситуацию. Есть таблица в которую посредством SQL запроса ложу данные, так как там необходимо в один столбец выводить несколько значений. Теперь встала проблема что при двойном клике по строке и вызове окна для редактирования программа ложится по сигналу полученному от операционки. я реализовал метод с использованием currentIndex()

                            edob = new editobject(ui->obv->selectionModel()->currentIndex().row());
                            edob экземляр формы для редактирования editobject, а obv таблица. при отладке выяснил что как только отрабатывает строка rmap->setCurrentModelIndex(rmod->index(row,0)); в форме редактирования, прилетает сигнал от операционной системы rmap = new QDataWidgetMappe как решить проблему. от QComboBox я на данном этапе отказался. у меня сама форма не отрабатывает
                              Evgenii Legotckoi
                              • May 21, 2017, 10:30 p.m.

                              В смысле программа крашится и выдаёт Segmentation Fault?
                              Ну тогда обращаетесь видимо к объекту, который в данный момент не был инициализирован. Получается, что используете rmap раньше, чем этот объект был создан. Нужно перетряхнуть последовательность действий.

                                M
                                • May 22, 2017, 1:31 p.m.

                                rmap инициализируется после его создания. не знаю что сделал, код не правил, но все заработало. только вот есть косяк о котором ранее не задумался. так как таблица в которой происходит вызов окна редактирования формируется по sql запросу, то индексы актуальны только для одного набора данных, для остальных заполнение происходит не верно. в связи с чем возникает вопрос если для использования QSqlQuery или QSqlQueryModel. Но в первую очередь у меня проблема с тем что сохранение изменений не происходит. Делаю как и всегда mapper->submit() и model->submitAll(). в других случаях все нормально

                                  Evgenii Legotckoi
                                  • May 23, 2017, 11:53 a.m.

                                  Так вы используете model->submitAll() и при этом используете QSqlQueryModel в качестве этой model?

                                  Делаю как и всегда mapper->submit() и model->submitAll(). в других случаях все нормально

                                  Я фиксить баги по таким высказываниям не умею, а экстрасенсы в отпуске. Код показывать следует в таких случаях.

                                    M
                                    • May 23, 2017, 11:55 a.m.

                                    нет. model = new QSqlTableModel

                                      M
                                      • May 23, 2017, 11:57 a.m.

                                      QSqlQueryModel я использую для формирования визуальной таблицы из которой по двойному клику вызываю форму редактирования. в ней же использую стандартный подход QSqlTableModel и QDataWidgetMapper

                                        Evgenii Legotckoi
                                        • May 23, 2017, 12:36 p.m.

                                        Тогда после применения настроек в форме редактирования, применяйте обновление данных в вашей QSqlQueryModel.

                                          M
                                          • May 23, 2017, 12:38 p.m.

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

                                            M
                                            • May 23, 2017, 1:47 p.m.

                                            Никак не могу найти способ чтобы обойти проблему с индексами в форме приведенной на скриншоте. в этой форме отображается информация, о которой говорил ранее, ее я и редактирую. заполнение данной формы происходит при помощи QSqlQueryModel и по ряду показателей. проблема в том что если я меняю значение показателя (критерия отбора) то при выводе в таблицу индексы строк обновляются, т.е. они всегда идут с значения "1", что не соответствует индексу строки в sql таблице. Как результат форма редактирования заполняется не верно. Возможно из-за этого и не отрабатывает обновление данных

                                              Evgenii Legotckoi
                                              • May 23, 2017, 2:38 p.m.

                                              Потому, что это не ID, а номера строк самой таблицы. Почитайте вот это сообщение , да и в принципе весь топик.

                                                M
                                                • May 23, 2017, 3:11 p.m.

                                                вообще-то я делаю передачу индекса

                                                edob = new editobject(rrid, rayid, ui->obv->selectionModel()->currentIndex().row());
                                                где obv та самая таблица из которой я дергую информацию. а editobject форма для редактирования. в editobject индекс я использую в
                                                rmap->setCurrentModelIndex(rmod->index(row,0));
                                                rmap = new QDataWidgetMapper.

                                                  Evgenii Legotckoi
                                                  • May 23, 2017, 3:27 p.m.

                                                  И дальше что? То, что вы привели мне две эти строчки ещё не говорит о том, что этот код работает правильно.

                                                  И вообще-то QModelIndex != ID в базе данных, index.row() != ID в базе данных

                                                  Он у Вас работает правильно? Вы получаете обновление данных в базе данных? - НЕТ . Иначе это обсуждение не длилось бы так долго.

                                                  А теперь, я увижу достаточно подробный код или нет? 

                                                    M
                                                    • May 23, 2017, 3:47 p.m.

                                                    Код форм про которые говорил прикрепил. regrdit форма в которой отображается информация отбираемая из базы. editobject форма для редактирования

                                                      Evgenii Legotckoi
                                                      • May 28, 2017, 8:01 p.m.

                                                      Как интересно. У вас используется выборка по условиям везде. Ничего удивительного, что когда создаёте editobject , то получаете не верные данные. Забирая номер строки из одной таблицы, пытаетесь с помощью него получить другие данные в другой таблице. В которой используются совершенно другие условия выборки. Как я и говорил, почитайте топик, что я Вам привёл выше. И забирайте данные не по номеру строки в модели, а по ID записи в базе данных.

                                                      P/S/ Код у Вас отвратительный. Если кто-то после вас будет работать с проектом, то ему проще будет написать программу заново.

                                                        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