![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Связанные таблицы [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.