Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Связанные таблицы [D7, Firebird]


kalliopiy ©   (2004-04-21 17:21:00) 

Здравствуйте!

Подскажите как выйти из следующей ситуации. Есть две связанные таблицы, например, Организации (главная) и Подразделения (подчиненная). В БД создан внешний ключ для таблицы подразделений на таблицу организаций. При попытке внесения новой записи в таблицу организаций, а потом заполнения для этой организации ее подразделений, возникает ошибка violation of Foreign Key. Т.е. пока не сохранена запись с новой организацией нельзя внести для нее подразделения. Причем сохранена она должна быть не просто через Post, но еще и через Commit для соответствующей транзакции.

Возможно ли как-то сделать так, чтобы одновременно можно было бы вносить новую запись в главную таблицу, а потом несколько записей в подчиненную да еще и так, чтобы в случае отмены можно было бы сделать на все это общий откат (Rollback)?


Sergey13   (2004-04-22 11:00:00) [1]

2kalliopiy
Поставь перед
divisionsDS.Append;
showmessage или отладчиком посмотри firmsDS.FieldByName('id').
Может ошибка где то в другом месте кода если один раз проходит, а другой нет.

2Johnmen ©   (22.04.04 10:30) [18]
>Казалось бы, причём здесь TTable ?
>:)
Зато как мощно задвинул. Особенно про SQL платформу. 8-)


Johnmen   (2004-04-22 10:30:00) [2]

Казалось бы, причём здесь TTable ?
:)


фыва   (2004-04-22 10:23:00) [3]

Мне кажется, надо просто написать хранимую процедуру. Все описанные действия реализуются в ХП.
Работать с SQL сервером через TTable - это переносить логику xBase & Paradox, т.е. файл-серверных платформ на SQL, что не есть правильно. Вообще-то, бизнес логика приложения на SQL платформе должна танцевать от запросов и хранимых процедур а не TTablов.


Johnmen   (2004-04-22 09:13:00) [4]

>kalliopiy   (21.04.04 18:27) [13]
>Так а как лучше сделать,...

Я думаю лучше сначала получить очередное значение генератора, а потом его использовать в приложении. Получить можно запросом, можно с помощью ХП, можно неявно, указав в необходимые значения в AutoUpdateOptions DataSet'а (FIB+).


kalliopiy   (2004-04-21 18:33:00) [5]


> Соловьев ©   (21.04.04 18:30) [14]


Есть такая проверка, а как же :))!


Соловьев   (2004-04-21 18:30:00) [6]


> Дело в том, что для таблицы Организаций у меня в БД создан
> триггер, который автоинкрементирует поле id.

должна быть обязательно проверка
if(New.Id is NULL)then New.Id = Gen_id(gen_name, 1);


kalliopiy   (2004-04-21 18:27:00) [7]


> Johnmen ©   (21.04.04 18:23) [12]


Так а как лучше сделать, подскажите пожалуйста, потому что мне важнее понять как сделать правильнее, чем просто исправить ошибку!

Кстати, если убрать из триггера манипуляции с генератором, то получится, что он будет пустой (т.е. ничего делать не будет)


Johnmen   (2004-04-21 18:23:00) [8]

>kalliopiy   (21.04.04 18:18) [11]

Конечно ! Это ошибка. Выкинь из триггера манипуляции с генератором.
(Но я бы сделал идеологически по-другому)


kalliopiy   (2004-04-21 18:18:00) [9]

2 Johnmen

Я тоже думаю, что так не должно быть и кажется я понял где у меня подвох.

Дело в том, что для таблицы Организаций у меня в БД создан триггер, который автоинкрементирует поле id. Но вот в Делфи я для соответствующего Датасета сделал GeneratorField (указав этот самы триггер и поле, а инкремент 1) и теперь он в гриде мне показывает одно id, а в базу попадает по-моему значение на единицу меньше.

Так как тут лучше выкрутиться?


Johnmen   (2004-04-21 18:12:00) [10]

>Соловьев ©   (21.04.04 18:09) [9]

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


Соловьев   (2004-04-21 18:09:00) [11]


> Johnmen ©   (21.04.04 18:02) [8]

т.е. Вы хотите сказать, что получив на клиенте id мастера, но не внеся его в БД(commit) можно добавлять с таким же id в детайл?


Johnmen   (2004-04-21 18:02:00) [12]

>Соловьев ©   (21.04.04 18:00) [7]

Ничего подобного.
:)


Соловьев   (2004-04-21 18:00:00) [13]


> Johnmen ©   (21.04.04 17:53) [6]

так как транзакция не подтверждена - то понятно то на уровне БД происходит исключение. Нужно сначала закомитить мастера, а потом только вносить данные в детайл


Johnmen   (2004-04-21 17:53:00) [14]

>Так я же так и делаю! И даже в гриде видно, что id и firmID
>одинаковые, но ошибка все равно выдается

Лучше в этом убедиться при присваивании.


kalliopiy   (2004-04-21 17:45:00) [15]

:)) Так я же так и делаю! И даже в гриде видно, что id и firmID одинаковые, но ошибка все равно выдается

И Датасеты ведь под одной транзакцией работают, вроде же все правильно должно быть


Johnmen   (2004-04-21 17:39:00) [16]

Присваивать
divisionsDS.FieldByName('firmID').AsInteger
существующее значение из firmsDS


kalliopiy   (2004-04-21 17:34:00) [17]


> После Post вставляй в подчинённую. А потом Commit/Rollback.


Я-то так и делаю. Т.е. примерно такой код в OnClick'e кнопки "Добавить подразделение"

if firmsDS.FieldByName('id').IsNull then firmsDS.Post;
divisionsDS.Append;
divisionsDS.FieldByName('firmID').AsInteger:=firmsDS.FieldByName('id').AsInteger;


Первый раз все проходит нормально и можно заполнять поля для Подразделения, но как только нажимаешь на эту кнопку еще раз, т.е. производится Post предыдущего Подразделения и попытка добавить новое (ну, вобщем-то до этого и не доходит, т.к. на Post-е уже облом), то сразу выдается вышеописанная ошибка.

Что ж делать-то?


dimm22   (2004-04-21 17:25:00) [18]


> Возможно ли как-то сделать так, чтобы одновременно можно
> было бы вносить новую запись в главную таблицу, а потом
> несколько записей в подчиненную да еще и так, чтобы в случае
> отмены можно было бы сделать на все это общий откат (Rollback)?

С помощью триггеров.


Johnmen   (2004-04-21 17:24:00) [19]

>Причем сохранена она должна быть не просто через Post, но еще и
>через Commit для соответствующей транзакции.

После Post вставляй в подчинённую. А потом Commit/Rollback.


Наверх

Титульная страница Поиск, карта сайта Написать письмо