Страница 1 из 1

Транзакции в MyQuery

Добавлено: Вт 20 мар 2012 12:00
imobile
Подскажите, как правилно пользоваться транзакциями.
У меня есть несколко запросов, типа UPDATE и SELECT но разными query на разных формах, мне надо в случае ошибки данные не записывать.
Где можно посмотреть примеры с MyQuery работающие с SET AUTOCOMMIT, BEGIN,COMMIT,ROLLBACK? Можно их использовать, когда разные Query?Будут они связанные между собой в разных Query или будут независимые?

Добавлено: Ср 21 мар 2012 10:23
AndreyZ
Примеры:

Код: Выделить всё

MyQuery.Connection := MyConnection;
MyQuery.SQL.Text := 'select * from tablename';
MyQuery.Open;
MyConnection.ExecSQL('set autocommit = 0', []);
try
  MyQuery.Edit;
  MyQuery.FieldByName('fieldname').AsString := 'test';
  MyQuery.Post;
  MyConnection.ExecSQL('commit', []);
except
  MyConnection.ExecSQL('rollback', []);
end;

Код: Выделить всё

MyQuery.Connection := MyConnection;
MyQuery.SQL.Text := 'select * from tablename';
MyQuery.Open;
MyConnection.ExecSQL('start transaction', []);
try
  MyQuery.Edit;
  MyQuery.FieldByName('fieldname').AsString := 'test';
  MyQuery.Post;
  MyConnection.ExecSQL('commit', []);
except
  MyConnection.ExecSQL('rollback', []);
end;
Вместо использования данных MySQL запросов мы советуем использовать методы StartTransaction, Commit и Rollback компонента TMyConnection. Пример:

Код: Выделить всё

MyQuery.Connection := MyConnection;
MyQuery.SQL.Text := 'select * from tablename';
MyQuery.Open;
MyConnection.StartTransaction;
try
  MyQuery.Edit;
  MyQuery.FieldByName('fieldname').AsString := 'test';
  MyQuery.Post;
  MyConnection.Commit;
except
  MyConnection.Rollback;
end;
Транзакция открывается для сессии, поэтому все изменения в разных датасетах использующих одну сессию будут приниматься или откатываться одновременно.

Добавлено: Ср 21 мар 2012 10:49
imobile
СПАСИБО БОЛЬШОЕ, как просто все оказывается.

Re: Транзакции в MyQuery

Добавлено: Ср 16 май 2012 20:13
Jonnik
Почему у меня не работает так транзакция?

Сдесь более продробно расписано http://www.sql.ru/forum/actualthread.aspx?tid=941472

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


Код: Выделить всё

 try
        DM.MyConnection1.StartTransaction;
        
            with DM.MyQuery1 do
              begin
                Close;
                sql.text:='INSERT INTO Org(  ID_Tip_O, NK, ND,  Kom)'
                +' VALUES ( :ID_Tip_O, :NK, :ND, :Kom)';
                Params[0].Value:=s[12];
                Params[1].Value:=s[2];
                Params[2].Value:=s[3];
                Params[3].Value:=s[4];
                ExecSQL;
              end;

            if ListView1.Items.Count>0 then
              begin
                for i:=0 to ListView1.Items.Count-1 do
                  begin
                    with DM.MyQuery1 do
                      begin
                        Close;
                        sql.text:='INSERT INTO Org_Kont( ID_Org, ID_Tip, N)'
                        +' VALUES ( :ID_Org, :ID_Tip, :N)';
                        Params[0].Value:=s[15];
                        Params[1].Value:=s[16];
                        Params[2].Value:=ListView1.Items[i].SubItems[2];
                        ExecSQL;
                      end;
                  end;
              end;

          end;
        DM.MyConnection1.Commit;
      except
        DM.MyConnection1.Rollback;
        
      end;


Re: Транзакции в MyQuery

Добавлено: Чт 17 май 2012 10:25
AndreyZ
Данная проблема вызвана установкой свойства TMyQuery.FetchAll в False. Если FetchAll=True , TMyQuery получает с сервера все данные сразу, если FetchAll=False , данные получаются по мере необходимости, что позволяет экономить ресурсы клиента. Но при FetchAll=False выполнение запросов блокирует текущую сессию. Для избежания этого MyDAC создает дополнительную сессию, которая выполняется вне контекста транзакции. Это приводит к тому что методы TMyConnection.Commit и TMyConnection.Rollback главной сессии не учитывают изменений сделанных в дополнительных сессиях. Для решения проблемы Вы можете использовать один из следующих подходов:
1. Установить TMyQuery.FetchAll в True.
2. Оставить TMyQuery.FetchAll=False и установить TMyQuery.Options.CreateConnection в False. TMyQuery.Options.CreateConnection определяет создавать или нет дополнительные сессии.
3. Использовать компонент TMyCommand вместо TMyQuery для выполнения запросов не возвращающих данных (INSERT, UPDATE, DELETE).

Re: Транзакции в MyQuery

Добавлено: Чт 17 май 2012 16:10
Jonnik
Спасибо.

Re: Транзакции в MyQuery

Добавлено: Пт 18 май 2012 08:04
AndreyZ
Я рад что смог помочь. Если у Вас возникнут дальнейшие вопросы по MyDAC, пишите нам.

Re: Транзакции в MyQuery

Добавлено: Чт 25 дек 2014 22:50
readiv
Понекропостю.

Код: Выделить всё

  con1.StartTransaction;
  try
    myqry1.SQL.Clear;
    myqry1.SQL.Add('INSERT INTO shop_brands (url) VALUES ('+QuotedStr(Translit_URL(S))+');');
    myqry1.SQL.Add('SELECT @@IDENTITY;');
    myqry1.ExecSQL;
    id:=myqry1.Fields[0].AsInteger;
    myqry1.SQL.Add('INSERTtttt INTO shop_brands_i18n (id,locale,name,meta_title,meta_description,meta_keywords) VALUES ('+
                   IntToStr(id)+', ''ru'', ' +
                   QuotedStr(S)+', '+QuotedStr(S)+', '+QuotedStr(S)+', '+QuotedStr(S)+');');
    myqry1.ExecSQL;
    con1.Commit;
  except
    con1.Rollback;
  end;
INSERTtttt - ошибка сделана специально что бы вызвать исключение. После исключения должен отработать Rollback и откатить первый INSERT, но этого не происходит. Вместо этого в этой таблице создаются аж 2 :shock: индентичные записи. FetchAll = True. CreateConnection = False.

Пробовал с MyConnection.ExecSQL('set autocommit = 0', []); результат тот же. Посоветуйте в какую сторону копать.

Re: Транзакции в MyQuery

Добавлено: Пт 26 дек 2014 12:24
ViktorV
К сожалению, мы не смогли воспроизвести проблему описанным Вами способом. Пожалуйста, обновите MyDAC до последней версии (8.4.12) и, если это не решит проблему, пришлите небольшой пример на viktorv*devart*com, демонстрирующий проблему, включающий скрипт на создание и заполнение таблиц БД.
2 идентичные записи в таблице "shop_brands" создаются потому, что Вы используете метод myqry1.SQL.Add и после второго вызова myqry1.ExecSQL опять выполняется запрос "INSERT INTO shop_brands", для решение этой проблемы Вы можете использовать вместо метода myqry1.SQL.Add свойство myqry1.SQL.Text или перед вызовом myqry1.SQL.Add вызвать метод myqry1.SQL.Clear.

Re: Транзакции в MyQuery

Добавлено: Вс 21 янв 2018 23:32
Goris
Здравствуйте!
Работаю в Delphi 7, установлен MyDAC 7.1.6.

Есть tDBGridEh, связанный с tDataSource-tMyQuery-tMyConnection
Таблица в БД MySQL типа InnoDB. Свойство MyQuery.FetchAll=true.

При создании формы ставлю MyConnection1.StartTransaction
В DBGridEh редактирую данные, потом жму на соответствующую кнопку для MyConnection1.Commit либо MyConnection1.Rollback.
Выяснилось, что в любом случае происходит запись данных в таблицу, Rollback не срабатывает, ошибок при этом не возникает. Насчет работы Commit ничего не могу сказать, т.к. запись происходит как при его наличии, так и при его отсутствии.
Попытка писать через MyConnection.ExecSQL('set autocommit = 0', []); и MyConnection.ExecSQL('rollback', []); также не работает - нет отмены транзакции.

Перечитал практически весь форум, перепробовал предлагаемые варианты, решения моего вопроса не нашел. Подскажите, как идет работа с транзакциями, может чего пропустил.

Re: Транзакции в MyQuery

Добавлено: Вт 23 янв 2018 05:21
Goris
вопрос перенес в новую тему

Re: Транзакции в MyQuery

Добавлено: Вт 23 янв 2018 13:52
ViktorV
Мы ответили вам на форуме viewtopic.php?t=14285