Как получить исполняемый оператор SQL, связанный с QSqlTableModel::setData()?

Я вставляю/обновляю таблицу базы данных из приложения Qt, используя QSqlTableModelметоды setData, submitAll и commit. Для целей ведения журнала мне нужно записать соответствующие операторы SQL. Как я могу это сделать? (Я смотрю на QSqlTableModel::query(), но кажется, что он возвращает только SELECT)

Вот упрощенная версия того, что я делаю.

QSqlTableModel *_dataTableModel = qobject_cast<QSqlTableModel*>(dataTableView->model());
_dataTableModel->setData(item, value);
_dataTableModel->database().transaction();
_dataTableModel->submitAll();
_dataTableModel->database().commit()
QSqlQuery _currentQuery = _dataTableModel->query();
qDebug() << _currentQuery.lastQuery();

Последняя строка всегда печатает SELECT, даже когда я делаю обновление или вставку.


Обновить

Вот самодостаточный фрагмент кода. Настройка такова, что у меня есть пользовательский интерфейс с QTableView и QPushButton. clicked() сигнал кнопки фиксируется в слоте addNewRow() и произвольное значение вставляется в первую ячейку. Я печатаю результат lastQuery(), ожидая, что это будет оператор вставки, но это оператор SELECT для данной таблицы. Что я делаю не так?

main.cpp

{
    QApplication a(argc, argv);
    test1 w;
    // connect to and open database
    w.setDataTable("MY_TEST_TABLE");
    w.show();
    return a.exec();
}

test1.h

public:
    void setDataTable(QString dataTableName);

private slots:
    void addNewRow();

test1.cpp

void test1::setDataTable( QString dataTableName )
{
    QSqlTableModel *tableModel = new QSqlTableModel(); 
    tableModel->setTable(dataTableName);
    tableModel->select();   
    ui.tableView->setModel(tableModel);
}

void test1::addNewRow()
{
    QSqlTableModel *tableModel = qobject_cast<QSqlTableModel*>(ui.tableView->model());
    if(!tableModel->insertRow(tableModel->rowCount())) {
            return;
    }       
    tableModel->setData(tableModel->index(0, 0), QVariant("123345")); 
    tableModel->database().transaction(); 
    if(!tableModel->submitAll()) {
            return;
    }  
    if (!tableModel->database().commit()) {                                          
            return;
    }     
    qDebug() << tableModel->query().lastQuery();
} 

person fortytwo    schedule 26.12.2013    source источник
comment
Вам нужно будет предоставить автономный пример, воспроизводящий проблему. Пожалуйста, обратитесь к sscce.org.   -  person lpapp    schedule 26.12.2013
comment
Это еще не самодостаточный пример. Там только куски кода. Пожалуйста, приведите пример, который мы можем запустить навскидку и проанализировать операцию. Пожалуйста, обратитесь к sscce.org.   -  person lpapp    schedule 26.12.2013
comment
Я не смог найти решение для этого. В качестве ссылки на людей, которые столкнутся с той же проблемой в будущем, вам придется явно создавать SQL и использовать exec(), а затем executedQuery().   -  person fortytwo    schedule 03.01.2014
comment
это тоже то, что я написал, так что же здесь остается решить?   -  person lpapp    schedule 03.01.2014
comment
Это утомляет. Вы упомянули этот метод И вы также упомянули «или вы также можете использовать следующий метод для запроса последнего оператора, если он выполняется динамически», и продолжил описание того, как я могу получить последний запрос из модели. Второй способ не работает. Я достаточно ясно здесь?   -  person fortytwo    schedule 03.01.2014
comment
Как я уже писал, у меня (и у многих других) работают оба способа, а вы еще не привели самодостаточный пример. В любом случае, я дал резервную операцию, что делать, если первая не работает, так что ваша проблема решена в любом случае? Что мы можем сделать, если мы не можем воспроизвести вашу проблему, а вы не предоставили пример, совместимый с sscce.org?   -  person lpapp    schedule 03.01.2014
comment
Это все еще не решено спустя год??   -  person lpapp    schedule 21.12.2014
comment
Да. Я использую первый метод. Метод, с которым у меня был вопрос, все еще не работает для меня.   -  person fortytwo    schedule 22.12.2014


Ответы (1)


На основе официальной документации:

Вставка, обновление и удаление записей

QSqlQuery может выполнять произвольные операторы SQL, а не только SELECT. В следующем примере запись вставляется в таблицу с помощью INSERT: запрос QSqlQuery; query.exec("ВСТАВИТЬ В сотрудника (идентификатор, имя, зарплата) " "ЗНАЧЕНИЯ (1001, 'Тад Бомонт', 65000)");

Это работает с любыми операторами, а не только с select. Если вы делаете это таким образом в необработанном режиме, вы всегда можете сначала создать QString и использовать его для операции QSqlQuery::exec(), а затем зарегистрировать его, или вы также можете использовать следующий метод для запроса последней инструкции, например, если это выполняется динамически:

QString QSqlQuery::lastQuery() константа

Возвращает текст текущего используемого запроса или пустую строку, если текущий текст запроса отсутствует.

Итак, осталось только узнать, как получить объект запроса из класса вашей модели. Это можно сделать с помощью следующего метода:

QSqlQuery QSqlQueryModel::query() константа

Возвращает QSqlQuery, связанный с этой моделью.

person lpapp    schedule 26.12.2013
comment
Спасибо. Но дело в том, что я не конструирую QSqlQuery. Что я делаю, так это используя QSqlTableModel (точнее, его подкласс), setData(), а затем submit(). Я реализовал queryChange(), чтобы увидеть, действительно ли этот запрос изменяется после отправки, и это так. Не могу понять, почему я не могу получить SQL с помощью lastQuery(). Немного повозившись, посмотрим, что получится. - person fortytwo; 26.12.2013
comment
@RaggS: вы можете получить QSqlQSquery из QSqlTableModel, используя метод доступа query()... - person lpapp; 26.12.2013
comment
Ласло Папп› Для ясности добавил фрагмент кода к исходному вопросу. - person fortytwo; 26.12.2013
comment
@Raggs: кроме того, как я уже писал в своем ответе, вы всегда можете составить запрос самостоятельно ... Хотя я нахожу немного необычным регистрировать операторы sql, а не операции Qt. - person lpapp; 26.12.2013
comment
Ласло Папп› Если вы еще раз прочитаете вопрос, я сказал, что именно это я и делал; QSqlTableModel setData, submitAll and commit, а затем querying. - person fortytwo; 26.12.2013
comment
Laszlo Papp› И чтобы ответить, почему мне нужны операторы SQL, а не операции Qt, мне нужны SQL, чтобы я мог выполнять те же операции с другой базой данных в виде макроса. - person fortytwo; 26.12.2013
comment
@Raggs: нет, вы не упомянули ни query(), ни lastQuery(). Пожалуйста, дважды проверьте историю. Вы даже не поняли, как получить класс запроса из модели. В любом случае, удачи, чтобы найти то, что вы ищете. Я пока не понимаю, что это такое. Такое ощущение, что ты пытаешься понять, чего ты хочешь. Трудно помочь на сцене. - person lpapp; 26.12.2013
comment
Мне нужны SQL, чтобы я мог выполнять те же операции с другой базой данных в виде макроса -> Ой. Звучит как неоптимальная идея для меня. Я бы либо воспроизвел операцию Qt, либо использовал команды SQL, как в моем ответе. - person lpapp; 26.12.2013
comment
Пожалуйста, прочтите еще раз. В скобках я упомянул, что «смотрю на QSqlTableModel::query(), но кажется, что он возвращает только SELECT» - person fortytwo; 26.12.2013
comment
И зачем мне нужны операторы SQL, так это то, что у меня нет доступа ко второй БД. Это интеграционная БД, в которой изменения вносятся с использованием (кем-то с правами доступа) запросов на регистрацию с необходимыми SQL. - person fortytwo; 26.12.2013
comment
Пожалуйста, прочтите еще раз. В скобках я упомянул, что «смотрю на QSqlTableModel::query(), но кажется, что он возвращает только SELECT» -> После моего ответа, да. - person lpapp; 26.12.2013
comment
И зачем мне нужны операторы SQL, так это то, что у меня нет доступа ко второй БД. Это интеграционная БД, в которой изменения вносятся с использованием (кем-то с правами доступа) запросов на регистрацию с необходимыми SQL. -› Мой ответ дает, что можно и что нельзя делать, на мой взгляд. Не уверен, что еще вам нужно. Более того, Вы не предоставили ни одного понятного примера, воспроизводящего проблему. Я действительно не могу. - person lpapp; 26.12.2013
comment
Проверить историю вопросов. Часть о query в скобках находится в исходном вопросе. Единственный раз, когда я редактировал вопрос, нужно было добавить биты кода. Итак, как я могу прочитать ваш комментарий еще до того, как задал свой вопрос? Я очень ценю вашу добровольную помощь, но, пожалуйста, будьте уважительны даже к такому новичку, как я. Мы здесь не для того, чтобы красть ваши идеи, мы пытаемся получить помощь. - person fortytwo; 26.12.2013
comment
Речь не идет о краже идеи, но трудно помочь, если вопрос радикально изменится. При этом я писал по крайней мере 2-3 раза, как вы можете получить то, что хотите иметь, хотя я думаю, что это странный вариант использования. Я не уверен, какая еще информация вам нужна, и, судя по пинг-понгу об истории, вы, похоже, тоже не желаете ее разъяснять. Кроме того, обратите внимание, что я не могу воспроизвести вашу проблему, и вы также не предоставили автономный пример, который является минимумом для дальнейшей помощи. - person lpapp; 26.12.2013
comment
И снова вопрос ничуть не изменился. И если вы обратите внимание, я все это время говорил о том, что ваше решение не дает результатов, которые я ищу. Он не дает мне INSERT SQL. - person fortytwo; 26.12.2013
comment
Как написано в ответе, вы должны явно использовать вызов exec(), иначе у вас не будет возможности его получить. - person lpapp; 26.12.2013
comment
Но в вашем ответе говорится: «... используйте это для операции QSqlQuery::exec(), а затем запишите ее, или вы также можете использовать следующий метод... QString QSqlQuery::lastQuery() const, и теперь вы говорите, что есть только один способ. Я бы предпочел не создавать SQL, а затем вызывать exec(), поэтому все это время я пытался следовать вашему второму варианту, а теперь вы говорите мне, что это невозможно, и единственный способ — использовать exec()? Я более чем согласен с тем, что вы предлагаете возможные методы, но проголосовать за мой вопрос и предположить, что я сжульничал, было бы слишком экстремально. - person fortytwo; 26.12.2013
comment
Второго варианта нет. Вы можете получить последний запрос, если используете exec() с помощью предварительно созданной строки или с помощью метода lastQuery(). Более того, я дал объяснение своему отрицательному голосу. Проверьте, сколько downvoters делают это. Кроме того, я никогда не утверждал, что ты меня обманывал. Я только сказал, что следить за веткой сложнее, если я что-то пишу, а потом вы добавили это в свой вопрос. Это приводит к тому, что мой ответ бесполезен, и если мне все равно, беспорядок останется вокруг. :) - person lpapp; 26.12.2013
comment
И lastQuery() всегда дает мне SELECT даже сразу после INSERT. Я делаю что-то ужасно глупое здесь? - person fortytwo; 26.12.2013
comment
Даже если вы последуете примеру в связанной документации, то есть используете INSERT с необработанным exec и запросите последний? - person lpapp; 26.12.2013
comment
Нет. Я не использую raw exec. К сожалению, это не вариант с моей текущей задачей. Я устанавливаю данные для вставки через QSqlTableModel::setData(), затем делаю submit() и commit, а затем пробую lastQuery(). Кстати, вы хотите выложить все мои файлы, даже файл UI? - person fortytwo; 26.12.2013
comment
Нет. Я не использую raw exec. К сожалению, это не вариант с моей текущей задачей. -› Я не уверен, как еще вы попытаетесь решить или хотя бы отладить проблему, если у вас нет готовности к таким испытаниям... Кстати, не хотите ли выложить все мои файлы, даже файл UI ? -> какие? Даже приложение с однократным запуском из командной строки должно быть в порядке. Я не уверен, почему вы не читаете sscee.org. Sql не зависит от пользовательских интерфейсов, таких как GUI... - person lpapp; 26.12.2013