Почему создается впечатление, что создание ТАБЛИЦЫ выполняется успешно, но затем завершается неудачей в DBX?

#delphi #firebird #delphi-xe #dbexpress

#delphi #firebird #delphi-xe #dbexpress

Вопрос:

У меня есть соединение dbExpress, подключенное к базе данных Firebird, под управлением Firebird Embedded. Пока все работает нормально, но происходит что-то очень странное.

У меня есть модуль данных, который содержит соединение и несколько TSimpleDataset объектов, представляющих разные таблицы. Но когда я пытаюсь добавить новую таблицу, кажется, что она работает, но затем завершается неудачей:

 procedure Update(module: TdmDatabase);
const
   SQL = 'CREATE TABLE NEW_TABLE (blah blah blah)';
   SQL2 = 'ALTER TABLE NEW_TABLE ADD CONSTRAINT PK_NEW_TABLE PRIMARY KEY (blah)';
   SQL3 = 'DROP TABLE NEW_TABLE';
begin
   module.connection.ExecuteDirect(SQL);      //succeeds
   module.connection.ExecuteDirect(SQL2);     //succeeds
   try
     module.New_TableDataset.Active := true;  //fails
   except
     module.connection.ExecuteDirect(SQL3);   //succeeds
     raise;
   end;
end;
  

Когда я пытаюсь создать таблицу, кажется, что она работает, и я могу, ALTER и DROP это просто отлично, но когда я пытаюсь открыть dataset, который выполняет SELECT против него, я получаю ошибку «недопустимое имя таблицы». Если я запускаю его в отладчике и завершаю программу сразу после выполнения CREATE TABLE инструкции, затем проверяю базу данных, новой таблицы там нет.

Кто-нибудь знает, что могло вызвать это, и как я могу это исправить?

Комментарии:

1. Я не знаком с DBX, я использую IBX для Firebird, поэтому вот комментарий: убедитесь, что вы зафиксировали транзакцию, которую использовали для создания таблицы. Убедитесь, что ваш «New_TableDataset» активирован с помощью новой транзакции, он не активируется с помощью длительной транзакции, которая имеет другое представление системных таблиц.

2. Другие советы: я бы запускал большинство операций DDL в своей собственной транзакции, фиксируя после каждой из них. На самом деле в некоторых инструментах есть опция «автоматической фиксации операций DDL». И я бы определенно не смешивал DDL с обычными операциями.

3. Возможно, используйте компонент TSQLQuery вместо TSimpleDataset, который устарел.

4. @No’am: Устарело? В какой версии? Потому что этого, безусловно, нет в Delphi XE, и TSQLQuery не является подходящей заменой для него.

Ответ №1:

  1. Это похоже на проблему с чистой транзакцией, где SQL , SQL2 и SQL3 выполняются в одной (или во многих) транзакциях. И транзакция остается активной по крайней мере после этого SQL . И New_TableDataset работает в другой транзакции, которая, конечно, не видит незафиксированных изменений первой транзакции.
  2. Проблема не в DataSnap / dbExpress, а скорее в конкретной реализации драйвера. Итак, полезно знать, что это за драйвер. И необязательно обращаться в службу технической поддержки поставщика драйверов.
  3. Что делать (чистое предположение):
    • Попробуйте включить выполнение команд в явный контроль транзакций. Это будет (может) гарантировать, что транзакция завершена после требуемого шага.
    • Попробуйте выполнить COMMIT после SQL и / или SQL2 .
    • Попробуйте использовать TSQLQuery вместо ExecuteDirect . Надеюсь, все команды будут выполняться в одной транзакции.

PS: Наконец, рассмотрите возможность использования другого драйвера dbExpress или даже библиотеки доступа к данным.

Комментарии:

1. Спасибо. Включение CREATE TABLE в свою собственную явную транзакцию сработало.

Ответ №2:

У меня была аналогичная проблема с ADO, решение было :

1/ Как уже говорилось: выполните ФИКСАЦИЮ после всего вашего DDL SQL.

2/ Когда первое создание пройдет нормально, выполните запрос SELECT ( COMMIT) для созданной таблицы

Комментарии:

1. Если это не проблема с драйвером, совет «2» просто бесполезен. И если драйвер настолько плох, его следует заменить. Что касается «1», то его следует дополнить, указав, что ФИКСАЦИЯ должна следовать за инструкциями DDL (язык определения данных) — в нынешнем виде похоже, что ФИКСАЦИЯ должна следовать за всеми инструкциями SQL, и это явно неверно, потому что это подрывает всю концепцию использования транзакций, чтобы несколько операций выполнялись успешно или не выполнялись как группа.

2. @CosminPrund Я знаю, что 2 / кажется бесполезным, но в моем случае это было эффективно, и иногда драйвер не может быть заменен так просто, и более того: его легко протестировать. Я согласен с вашим 1 / замечанием: я отредактирую свой пост.