Поиск:

Ответ в темуСоздание новой темы Создание опроса
> обновление двух и более таблиц в одной транзакции 
V
    Опции темы
serega1983
Дата 2.10.2013, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.10.2013

Репутация: нет
Всего: нет



Доброго времени суток.
Есть база данных Firebird.
Необходимо реализовать списание товаров со склада.
Делаю следующее.
1) создаю расходную накладную
2) заполняю ее данными из таблицы склада
3) выставляю необходимо количество товара для списания
4) жму сохранить и записи из dataSet вставляются в таблицу расходная накладная
5) со склада вычитается кол-во товара, указанное в dataSet
Проблема возникает со списанием товара со склада.

Как делаю.

Таблицы
user posted image

Форма
user posted image

Код

FDataSet: TIBCustomDataSet;
ibQuery.cashedUpdate := true;




запрос для query
Код

select ss.amount,
       ss.ID,
       ss.product_id,
       s.title
from sales_invoice ss
join storehouse s
    on s.id            = ss.product_id
    and ss.register_id = :idDocument
order by s.title


Последний вариант моего "мучения" был такой 

Код

procedure TForm1.Button2Click(Sender: TObject);
var Q: TIBQuery;
begin
  try
      IBTransactionWriteoffProducts.StartTransaction;
      if FDataSet.RecordCount = 0 then begin
          raise Exception.Create('Документ пуст!');
      end;

      Q := TIBQuery.Create(nil);
      Q.Transaction := IBTransactionWriteoffProducts;
      FDataSet.First;
      while not FDataSet.Eof do begin
          if(FDataSet.CachedUpdateStatus = cusInserted) then begin
              Q.Close;
              Q.SQL.Clear;
              Q.SQL.Add('update storehouse set amount = amount - :amount where id = :id and amount - :amount >= 0');
              Q.Prepare;
              Q.ParamByName('id').AsInteger   := FDataSet.FieldByName('product_id').AsInteger;
              Q.ParamByName('amount').AsFloat := FDataSet.FieldByName('amount').AsFloat;
              Q.ExecSQL;

              if(Q.RowsAffected < 1) then begin
                  raise Exception.Create('Вы пытаетесь списать товаров больше чем их есть на складе. Товар "'
                                         + FDataSet.FieldByName('title').AsString + '" кол-во ' + FDataSet.FieldByName('amount').AsString);
              end;
          end;

          FDataSet.Next;
      end;


      FDataSet.Database.ApplyUpdates([FDataSet]);
      IBTransactionWriteoffProducts.Commit;
  except
      on E : Exception do begin
          IBTransactionWriteoffProducts.Rollback;
          ShowMessage(E.ClassName + ' ошибка : ' + E.Message);
      end;
  end;
end;

списание со склада проходит успешно, а вставка в расходную не происходит - ошибка транзакция уже активна. Почему так происходит я понимаю. Как это победить - не знаю.

Ответа на форумах ни в книгах найти не смог. Подскажите как правильно работать, с точки зрения компонентов, при изменении данных, больше чем в одной таблице или правильный подход к решению таких задач, возможно здесь компонент IBUpdateSql и не нужен вовсе.
PM MAIL   Вверх
DYUMON
Дата 2.10.2013, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 321
Регистрация: 17.6.2006
Где: Новосибирск

Репутация: 2
Всего: 3



если в птичке есть тригеры то кури в их сторону


--------------------
Всех программистов надо посадить на целероны, что бы впредь головой думали что пишут.
user posted image
PM MAIL ICQ Skype   Вверх
serega1983
Дата 2.10.2013, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.10.2013

Репутация: нет
Всего: нет



Цитата(DYUMON @ 2.10.2013,  11:20)
если в птичке есть тригеры то кури в их сторону

Не используя возможности БД(тригерры, хранимые процедуры), есть варианты?
PM MAIL   Вверх
Akella
Дата 2.10.2013, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 29
Всего: 329



Цитата(serega1983 @  2.10.2013,  11:00 Найти цитируемый пост)
ошибка транзакция уже активна.

Так а зачем ты её второй раз стартуешь?

Добавлено @ 15:19
Цитата(serega1983 @  2.10.2013,  11:00 Найти цитируемый пост)
Почему так происходит я понимаю. Как это победить - не знаю.

Значит не понимаешь.

Добавлено @ 15:20
Зачем используешь механизм cashedUpdate?

Добавлено через 5 минут и 22 секунды
У тебя обе операции должны проходить в рамках одной активной транзакции (IBTransactionWriteoffProducts). Обе квери должны быть подключены к одной и той же  транзакции.

Если условно, то так.
Код

if not IBTransactionWriteoffProducts.inTransaction then IBTransactionWriteoffProducts.Start;
Try
  списываешь товар
  добавляешь в расходную накладную
  IBTransactionWriteoffProducts.commit;
except
  IBTransactionWriteoffProducts.rollback;
end;

PM MAIL   Вверх
serega1983
Дата 2.10.2013, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.10.2013

Репутация: нет
Всего: нет



Цитата(Akella @ 2.10.2013,  15:19)
Так а зачем ты её второй раз стартуешь?


FDataSet.Database.ApplyUpdates([FDataSet]);
Здесь она стартует автоматически.

Цитата(Akella @ 2.10.2013,  15:19)
Значит не понимаешь.

Не исключаем такого варианта =)

Цитата(Akella @ 2.10.2013,  15:19)
Зачем используешь механизм cashedUpdate?


Для занесения изменений в БД после нажатия кнопочки "Сохранить"

Цитата(Akella @ 2.10.2013,  15:19)
У тебя обе операции должны проходить в рамках одной активной транзакции (IBTransactionWriteoffProducts). Обе квери должны быть подключены к одной и той же  транзакции.

Все привязано к транзакции IBTransactionWriteoffProducts;







PM MAIL   Вверх
serega1983
Дата 2.10.2013, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.10.2013

Репутация: нет
Всего: нет



Проблема решилась сама, но скорее всего было 

Цитата(Akella @  2.10.2013,  15:19 Найти цитируемый пост)
У тебя обе операции должны проходить в рамках одной активной транзакции (IBTransactionWriteoffProducts). Обе квери должны быть подключены к одной и той же  транзакции.


и это добавил
Цитата(Akella @  2.10.2013,  15:19 Найти цитируемый пост)

Код

if not IBTransactionWriteoffProducts.inTransaction then IBTransactionWriteoffProducts.Start;





Всем спасибо.

Это сообщение отредактировал(а) serega1983 - 3.10.2013, 09:29
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


Обязательно указание:

1. Базы данных (Paradox, Oracle и т.п.)

2. Способа доступа (ADO, BDE и т.д.)


  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • Вопросы по SQL и вопросы по базам данных не связанные с Дельфи задавать здесь

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема »


 




[ Время генерации скрипта: 0.0760 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.