Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Разработка баз данных _ Запрос вставки

Автор: AD 28.3.2011, 11:12

Есть запросы вставки записи в таблицу, подобные данной:

QSqlQuery query(QSqlDatabase::database("conn_1"));
query.prepare(QString("insert into ScriptLayer(ScriptItemId, LayerNameId) values(%1, -1)").arg(id));
bool ins = query.exec();
Проверяю. ins = true. При этом в саму таблицу ничего не добавилось. Как такое возможно? Естественно, что при закрытии приложения никаких удалений не делаю.

Автор: BRE 28.3.2011, 12:11

А если в программе sqlbrowser попробовать добавить запись в эту базу?

Как создается таблица ScriptLayer?

Автор: AD 28.3.2011, 12:42

Цитата(BRE @ 28.3.2011, 13:11) *
А если в программе sqlbrowser попробовать добавить запись в эту базу?

Не пробовал. Попробую.

P.S. Да, создается.
Цитата(BRE @ 28.3.2011, 13:11) *
Как создается таблица ScriptLayer?

Она по-умолчанию создана.

Автор: MJIbIu 28.3.2011, 15:18

Цитата(AD @ 28.3.2011, 11:12) *
query.prepare(QString("insert into ScriptLayer(ScriptItemId, LayerNameId) values(%1, -1)").arg(id));

А попробуй как вот так
query.prepare(QString("insert into nameDB.ScriptLayer(ScriptItemId, LayerNameId) values(%1, -1)").arg(id));

Автор: AD 28.3.2011, 15:40

Цитата(MJIbIu @ 28.3.2011, 16:18) *
А попробуй как вот так
query.prepare(QString("insert into nameDB.ScriptLayer(ScriptItemId, LayerNameId) values(%1, -1)").arg(id));

Что за nameDB? У меня ведь запрос-то выполняется... По какой-то причине при выходе из БД удаляется запись. Непонятно почему.

Автор: MJIbIu 28.3.2011, 15:52

Цитата(AD @ 28.3.2011, 15:40) *
Цитата(MJIbIu @ 28.3.2011, 16:18) *
А попробуй как вот так
query.prepare(QString("insert into nameDB.ScriptLayer(ScriptItemId, LayerNameId) values(%1, -1)").arg(id));

Что за nameDB? У меня ведь запрос-то выполняется... По какой-то причине при выходе из БД удаляется запись. Непонятно почему.

query.prepare("INSERT INTO ИмяБД.ИмяТаблице VALUES (:value1,:value2);");
query.bindValue(":valut1", "значение 1");
query.bindValue(":value", "значение 2");
я делаю так
Если бы у тебя запрос бы выполнялся тогда бы и в БД заносились бы данные.

Цитата(AD @ 28.3.2011, 15:40) *
По какой-то причине при выходе из БД удаляется запись.

:huh:
Ты с какой СУБД работаешь ?

Автор: AD 28.3.2011, 16:36

Цитата(MJIbIu @ 28.3.2011, 16:52) *
query.prepare("INSERT INTO ИмяБД.ИмяТаблице VALUES (:value1,:value2);");
query.bindValue(":valut1", "значение 1");
query.bindValue(":value", "значение 2");
я делаю так
Если бы у тебя запрос бы выполнялся тогда бы и в БД заносились бы данные.

При добавлении я вижу, что в таблице появилась новая запись, значит, все же, добавилась. На счет ИмяДБ хотел уточнить. Я правильно понимаю, что имеется в виду имя соединения или же имеется в виду имя следующее - QSqlDatabase::database("connectionName").databaseName();

Цитата(MJIbIu @ 28.3.2011, 16:52) *
:huh:
Ты с какой СУБД работаешь ?

SQLiteAdmin в качестве СУБД. http://sqliteadmin.orbmu2k.de/

Автор: MJIbIu 28.3.2011, 17:03

Цитата(AD @ 28.3.2011, 17:36) *
При добавлении я вижу, что в таблице появилась новая запись, значит, все же, добавилась. На счет ИмяДБ хотел уточнить. Я правильно понимаю, что имеется в виду имя соединения или же имеется в виду имя следующее - QSqlDatabase::database("connectionName").databaseName();

Цитата(MJIbIu @ 28.3.2011, 16:52) *
:huh:
Ты с какой СУБД работаешь ?

SQLiteAdmin в качестве СУБД. http://sqliteadmin.orbmu2k.de/

create database ИмяБД character set utf8; вот что я имел виду
если у тебя создается тогда это не важно
Важнее то что у тебя после выхода твоей проги не сохраняются данные.
Выложи полный код. И покопайся в СУБД мб она как то настроено хитро всяко бывает

http://www.mysql.ru/docs/gruber/mg23.html
КОГДА СДЕЛАННЫЕ ИЗМЕНЕНИЯ СТАНОВЯТСЯ ПОСТОЯННЫМИ
Смахивает на твою проблему

Автор: AD 29.3.2011, 11:24

Цитата(MJIbIu @ 28.3.2011, 18:03) *
http://www.mysql.ru/docs/gruber/mg23.html
КОГДА СДЕЛАННЫЕ ИЗМЕНЕНИЯ СТАНОВЯТСЯ ПОСТОЯННЫМИ
Смахивает на твою проблему

Да. Похоже на данную проблему. Как это в СУБД решить, пока не нашел.
/// Вcmaвka строк в таблицу AztPage
bool SqlFileModel::insertRowsAztPage(int row, int count)
{
    if(tableName() != QString("AztPage")) return false;

    QStringList chart_names(valueElement("Azt/ChartFiles", QStringList()).toStringList());
    QString chart_name(chart_names.at(row));
    int sz = rowCount(), id = sz,
        stump_group_of_pages_id = 1;            ///< TODO: номер группы страниц (затычка)
    if(id < 0) id = 0;
    ++id;
    for(int i=0; i<sz; ++i)
    {
        QString file_name(record(i).value("SpatialFilePath").toString());
        if(chart_names.at(row).toLower() == file_name.toLower())
            return false;
    }
    QSqlDatabase db(QSqlDatabase::database("conn_1"));
    QString query_string(QString("insert into AztPage(Id, SpatialFilePath, GroupOfPagesId) values(%1, '%2', %3)")
                .arg(id).arg(chart_names.at(row)).arg(stump_group_of_pages_id));
    QSqlQuery query(db), q(db);
    query.prepare(query_string);
    q.prepare(QString("COMMIT;"));
    bool res = query.exec(), res_commit = q.exec();
    QString err(q.lastError().text());
    if(!res) return false;

    return true;
}

res = true, res_commit = false;
И в БД не попадает при выходе из приложения.
В err данном случае попадает следующая фраза
Цитата
cannot commit transaction - SQL statements in progress Unable to fetch row

Данный код тоже выдает сообщение предупреждение
QSQLiteDriver* p_driver((QSQLiteDriver*)QSqlDatabase::database("conn_1").driver());
bool is = p_driver -> commitTransaction();
if(!is)
        emit display(p_driver -> lastError().text(), true, false);

Цитата
cannot commit transaction - SQL statements in progress Unable to commit transaction.
Есть варианты как сделать? Копаюсь в ассистенте. Пока ничего не нашел.

Автор: AD 29.3.2011, 15:17

Буду рад, если поможете. Не понимаю, как сделать правильный commit транзакции. Возвращает ошибку, указанную в предыдущем посте. Повторюсь, что это необходимо, чтобы БД приняла данные, т.е. чтобы данные сохранились в БД. На данный момент получается такая фигня, что я вижу добавленные данные во время работы приложения. Но как только я перезапускаю приложение, данных нет. Сделать так, чтобы commit в итоге стал true не получается....

Автор: AD 30.3.2011, 11:01

Неужели ни у кого не было подобной проблемы при работе с SQLite?

Автор: MJIbIu 30.3.2011, 13:07

Цитата(AD @ 29.3.2011, 16:17) *
Буду рад, если поможете. Не понимаю, как сделать правильный commit транзакции. Возвращает ошибку, указанную в предыдущем посте. Повторюсь, что это необходимо, чтобы БД приняла данные, т.е. чтобы данные сохранились в БД. На данный момент получается такая фигня, что я вижу добавленные данные во время работы приложения. Но как только я перезапускаю приложение, данных нет. Сделать так, чтобы commit в итоге стал true не получается....

bool QSqlDatabase::commit ()
Выполняет транзакцию в базу данных, если она поддерживается драйвером и уже была начата транзакция посредством transaction(). Возвращает true в случае успеха операции. В противном случае возвращает false.
Замечание: Для некоторых баз данных фиксация транзакции завершится неудачно и возвратит false, если использовалась active query базы данных для SELECT. Сделайте запрос inactive перед выполнением фиксации транзакции.

http://www.javatalks.ru/ntopic9646.php
конечно там на java ну смысл я думаю тот же

Автор: AD 30.3.2011, 13:26

Цитата(MJIbIu @ 30.3.2011, 14:07) *
bool QSqlDatabase::commit ()
Выполняет транзакцию в базу данных, если она поддерживается драйвером и уже была начата транзакция посредством transaction(). Возвращает true в случае успеха операции. В противном случае возвращает false.
Замечание: Для некоторых баз данных фиксация транзакции завершится неудачно и возвратит false, если использовалась active query базы данных для SELECT. Сделайте запрос inactive перед выполнением фиксации транзакции.

http://www.javatalks.ru/ntopic9646.php
конечно там на java ну смысл я думаю тот же

Я умею читать ассистент. setAutocommit - в Qt нет. Сделал для запроса clear(), не прокатило. Что еще возможно? Данную ссылку уже сам находил - не помогло. Запрос делаю неактивным, но в БД запись не попадает.

Автор: AD 31.3.2011, 11:38

Вернулся к СУБД Paradox. Решение на данную проблему найти не смог. Буду пробовать ускорять работу запросов в Paradox

Автор: AD 11.4.2011, 9:22

В связи с тем, что скорость работы на Paradox маленькая, перешел обратно на SQLite. Проблема осталась. Не удается внести и запомнить записи. При транзакции коммит не удается сделать.
Выдает следующее сообщение

Цитата
cannot commit transaction - SQL statements in progress Unable to commit transaction

Самое странное, что записи из файла он в таблицу вставил нормально. Кто может помочь с этой проблемой. Уже несколько дней мучаюсь, решить не получается. Буду благодарен за помощь.

Вот функция, в которой транзакция не выполняется.
Раскрывающийся текст

/// Вcmaвka строк в таблицу AztPage
bool SqlFileModel::insertRowsAztPage(int row, int count)
{
    if(tableName() != QString("AztPage")) return false;

    QSqlDatabase db(QSqlDatabase::database("conn_1"));
    bool trans = db.transaction();

    QSqlQuery check_query(db);
    check_query.prepare("select max(Id) from AztPage");
    bool is_sel = check_query.exec(), is_next = check_query.next();
    QStringList chart_names(valueElement("Azt/ChartFiles", QStringList()).toStringList());
    QString chart_name(chart_names.at(row));
    int sz = rowCount(), id = sz, stump_group_of_pages_id = 1;    ///< TODO: номер группы страниц (затычка)
    ++id;
    if(is_sel && is_next)
        id = check_query.value(0).toInt(),
        ++id;
    for(int i=0; i<sz; ++i)
    {
        QString file_name(record(i).value("SpatialFilePath").toString());
        if(chart_names.at(row).toLower() == file_name.toLower())
            return false;
    }
    string fname(chart_name.replace(QString(QString(".") + QFileInfo(chart_name).suffix()),
                        QString(""), Qt::CaseInsensitive).toStdString());
    char* string_name_chart(const_cast<char*> (fname.c_str()));
    QString query_string(QString("insert into AztPage(Id, SpatialFilePath, GroupOfPagesId) "
                        "values(%1, '%2', %3)").arg(id).
                        arg(chart_names.at(row)).arg(stump_group_of_pages_id));
    QSqlQuery query(QSqlDatabase::database("conn_1"));
    query.prepare(query_string);
    bool res = query.exec();

    bool comm = db.commit();
    if(!comm)
    {
        QString error_string(db.lastError().text());
        int error_number = db.lastError().type();
    }

    return res;
}


Автор: MoPDoBoPoT 11.4.2011, 21:41

Цитата(QtAssistant)
bool QSqlQuery::isActive () const
...
Note: Of particular interest is an active query that is a SELECT statement. For some databases that support transactions, an active query that is a SELECT statement can cause a commit() or a rollback() to fail, so before committing or rolling back, you should make your active SELECT statement query inactive using one of the ways listed above.

Попробуй перед фиксацией транзакции для всех активных запросах вызвать clear()

Автор: AD 12.4.2011, 9:32

Цитата(MoPDoBoPoT @ 11.4.2011, 22:41) *
Попробуй перед фиксацией транзакции для всех активных запросах вызвать clear()

Пробовал. Не помогает.

Автор: AD 12.4.2011, 14:18

В результате долгих копаний. Кое-что смог выяснить. Исходя из http://wiki.crossplatform.ru/index.php/SQLite:_%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0_%D0%91%D0%94_%D0%B8%D0%B7_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8_%D0%B2_%D1%84%D0%B0%D0%B9%D0%BB_%D0%B8_%D0%B8%D0%B7_%D1%84%D0%B0%D0%B9%D0%BB%D0%B0_%D0%B2_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C#.D0.9F.D0.BE.D0.B4.D0.BA.D0.BB.D1.8E.D1.87.D0.B5.D0.BD.D0.B8.D0.B5_SQLite_API статьи, выяснил, что БД SQLite может хранится в памяти, а может в файле. Вопрос. Как организовать правильное хранение в памяти? Т.е. что конкретно надо поменять в данном коде:

/// Функция для создания соединения с базой данных
bool createConnection(const QString& odbc_path)
{
    QSqlDatabase db(QSqlDatabase::database("conn_1"));
    if(db.isOpen()) db.close();

    db = QSqlDatabase::addDatabase("QSQLITE", "conn_1");
    db.setDatabaseName(odbc_path);

    if(!db.open())
    {
        QSqlError error(db.lastError());
        QMessageBox msg(QMessageBox::Critical, "Connections", error.text(), QMessageBox::Ok, 0);
        msg.exec();
        return false;
    }
    return true;
}

Куда это ":in_memory:" добавить? Ну и попутный вопрос к ViGOur: помнится где-то была статья и сборке плагина без сборки всего Qt. Дайте, пожалуйста, ссылку на эту статью. Заранее спасибо.

Автор: MoPDoBoPoT 12.4.2011, 21:19

Цитата(AD @ 12.4.2011, 10:32) *
Пробовал. Не помогает.

Возможно, что где-то ещё активные запросы, например, табличные модели.
Цитата(AD @ 12.4.2011, 15:18) *
Как организовать правильное хранение в памяти?

    db = QSqlDatabase::addDatabase("QSQLITE", "conn_1");
    db.setDatabaseName(":memory:");

Автор: AD 13.4.2011, 9:32

Цитата(MoPDoBoPoT @ 12.4.2011, 22:19) *
Возможно, что где-то ещё активные запросы, например, табличные модели.

А как в табличных моделях сделать неактивными запросы?

Автор: AD 14.4.2011, 10:38

Либо я чего-то не понял, либо еще что-то, но загружать БД в память, а потом сохранять в файл не получилось. Прошу, кто может помочь, помогите, пожалуйста. Очень необходимо поправить глюк с транзакциями. Я не понимаю в чем ошибка...

Автор: MoPDoBoPoT 14.4.2011, 21:49

Цитата(AD @ 14.4.2011, 11:38) *
Либо я чего-то не понял, либо еще что-то, но загружать БД в память, а потом сохранять в файл не получилось.

Если только приаттачить (ATTACH DATABASE) файл БД, после чего переписать туда данные. Но лучше разобраться с проблемой транзакций и писать сразу в файл. Мне кажется, можно попробовать создать отдельное соединение для изменения данных в БД, чтобы не искать активные запросы и сбрасывать их.

Автор: AD 18.4.2011, 9:07

Цитата(MoPDoBoPoT @ 14.4.2011, 22:49) *
Если только приаттачить (ATTACH DATABASE) файл БД, после чего переписать туда данные. Но лучше разобраться с проблемой транзакций и писать сразу в файл. Мне кажется, можно попробовать создать отдельное соединение для изменения данных в БД, чтобы не искать активные запросы и сбрасывать их.

Сделал новое соединение, специально, чтобы делать выборки и вставки в БД. В итоге получил следующую ошибку при транзакции:
Цитата
database is locked Unable to commit transaction

Как решить эту проблему?

Автор: MoPDoBoPoT 19.4.2011, 21:29

Странно. Блокировку можно получить, когда в рамках разных транзакций происходит попытка изменения БД, но у тебя же одно подключение читает, а другое пишет... Может ещё быть из-за уровня изоляции транзакции EXCLUSIVE, но я не думаю, что ты его указывал.

Автор: AD 21.4.2011, 9:19

Цитата(MoPDoBoPoT @ 19.4.2011, 22:29) *
Странно. Блокировку можно получить, когда в рамках разных транзакций происходит попытка изменения БД, но у тебя же одно подключение читает, а другое пишет... Может ещё быть из-за уровня изоляции транзакции EXCLUSIVE, но я не думаю, что ты его указывал.

Тоже считаю, что странно. Но пока ничего не выходит. А проблему очень надо решить. Буду безумно благодарен, если сможешь помочь. Никаких EXCLUSIVE не использовал.

Автор: AD 21.4.2011, 17:01

О. Все-таки каких-то результатов удалось добиться. Смысл в том, что модель, унаследованная от QSqlTableModel блокирует базу данных, в результате чего возникают данные ошибки. Попробую разобраться в этом, тем более, что я видел, что QSqlLite как-то странно работает с моделями. Об этом я видел в ассистенте сообщение.

Автор: AD 22.4.2011, 13:59

Проблема решена. Дело вот в чем. Моя модель SqlFileModel наследовалась от QSqlTableModel, а у QSqlTableModel есть особенность при работе с SQLite она блокирует БД, пока не выполняться все ее select-запросы, что мне изрядно мешало.

Решение состоит в том, что модель стал наследовать от QAbstractTableModel. Тогда все вставки в таблицу происходят без проблем.

Автор: MoPDoBoPoT 22.4.2011, 21:09

Цитата(AD @ 22.4.2011, 14:59) *
она блокирует БД, пока не выполняться все ее select-запросы

В смысле не вычитает все записи по запросу? Типо этого?
 while (myModel->canFetchMore())
     myModel->fetchMore();

Автор: AD 22.4.2011, 23:08

Цитата(MoPDoBoPoT @ 22.4.2011, 22:09) *
В смысле не вычитает все записи по запросу? Типо этого?

Да.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)