Текущий архив: 2004.05.16;
Скачать: CL | DM;
Вниз
Связанные таблицы Найти похожие ветки
← →
kalliopiy (2004-04-21 17:21) [0]Здравствуйте!
Подскажите как выйти из следующей ситуации. Есть две связанные таблицы, например, Организации (главная) и Подразделения (подчиненная). В БД создан внешний ключ для таблицы подразделений на таблицу организаций. При попытке внесения новой записи в таблицу организаций, а потом заполнения для этой организации ее подразделений, возникает ошибка violation of Foreign Key. Т.е. пока не сохранена запись с новой организацией нельзя внести для нее подразделения. Причем сохранена она должна быть не просто через Post, но еще и через Commit для соответствующей транзакции.
Возможно ли как-то сделать так, чтобы одновременно можно было бы вносить новую запись в главную таблицу, а потом несколько записей в подчиненную да еще и так, чтобы в случае отмены можно было бы сделать на все это общий откат (Rollback)?
← →
Johnmen © (2004-04-21 17:24) [1]>Причем сохранена она должна быть не просто через Post, но еще и
>через Commit для соответствующей транзакции.
После Post вставляй в подчинённую. А потом Commit/Rollback.
← →
dimm22 (2004-04-21 17:25) [2]
> Возможно ли как-то сделать так, чтобы одновременно можно
> было бы вносить новую запись в главную таблицу, а потом
> несколько записей в подчиненную да еще и так, чтобы в случае
> отмены можно было бы сделать на все это общий откат (Rollback)?
С помощью триггеров.
← →
kalliopiy (2004-04-21 17:34) [3]
> После 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-е уже облом), то сразу выдается вышеописанная ошибка.
Что ж делать-то?
← →
Johnmen © (2004-04-21 17:39) [4]Присваивать
divisionsDS.FieldByName("firmID").AsInteger
существующее значение из firmsDS
← →
kalliopiy (2004-04-21 17:45) [5]:)) Так я же так и делаю! И даже в гриде видно, что id и firmID одинаковые, но ошибка все равно выдается
И Датасеты ведь под одной транзакцией работают, вроде же все правильно должно быть
← →
Johnmen © (2004-04-21 17:53) [6]>Так я же так и делаю! И даже в гриде видно, что id и firmID
>одинаковые, но ошибка все равно выдается
Лучше в этом убедиться при присваивании.
← →
Соловьев © (2004-04-21 18:00) [7]
> Johnmen © (21.04.04 17:53) [6]
так как транзакция не подтверждена - то понятно то на уровне БД происходит исключение. Нужно сначала закомитить мастера, а потом только вносить данные в детайл
← →
Johnmen © (2004-04-21 18:02) [8]>Соловьев © (21.04.04 18:00) [7]
Ничего подобного.
:)
← →
Соловьев © (2004-04-21 18:09) [9]
> Johnmen © (21.04.04 18:02) [8]
т.е. Вы хотите сказать, что получив на клиенте id мастера, но не внеся его в БД(commit) можно добавлять с таким же id в детайл?
← →
Johnmen © (2004-04-21 18:12) [10]>Соловьев © (21.04.04 18:09) [9]
Я хочу сказать, что стартовав тр-ию и добавив запись в мастера, можно сразу добавлять в деталь, не разделяя эти вставки коммитом/роллбеком...
← →
kalliopiy (2004-04-21 18:18) [11]2 Johnmen
Я тоже думаю, что так не должно быть и кажется я понял где у меня подвох.
Дело в том, что для таблицы Организаций у меня в БД создан триггер, который автоинкрементирует поле id. Но вот в Делфи я для соответствующего Датасета сделал GeneratorField (указав этот самы триггер и поле, а инкремент 1) и теперь он в гриде мне показывает одно id, а в базу попадает по-моему значение на единицу меньше.
Так как тут лучше выкрутиться?
← →
Johnmen © (2004-04-21 18:23) [12]>kalliopiy (21.04.04 18:18) [11]
Конечно ! Это ошибка. Выкинь из триггера манипуляции с генератором.
(Но я бы сделал идеологически по-другому)
← →
kalliopiy (2004-04-21 18:27) [13]
> Johnmen © (21.04.04 18:23) [12]
Так а как лучше сделать, подскажите пожалуйста, потому что мне важнее понять как сделать правильнее, чем просто исправить ошибку!
Кстати, если убрать из триггера манипуляции с генератором, то получится, что он будет пустой (т.е. ничего делать не будет)
← →
Соловьев © (2004-04-21 18:30) [14]
> Дело в том, что для таблицы Организаций у меня в БД создан
> триггер, который автоинкрементирует поле id.
должна быть обязательно проверка
if(New.Id is NULL)then New.Id = Gen_id(gen_name, 1);
← →
kalliopiy (2004-04-21 18:33) [15]
> Соловьев © (21.04.04 18:30) [14]
Есть такая проверка, а как же :))!
← →
Johnmen © (2004-04-22 09:13) [16]>kalliopiy (21.04.04 18:27) [13]
>Так а как лучше сделать,...
Я думаю лучше сначала получить очередное значение генератора, а потом его использовать в приложении. Получить можно запросом, можно с помощью ХП, можно неявно, указав в необходимые значения в AutoUpdateOptions DataSet"а (FIB+).
← →
фыва (2004-04-22 10:23) [17]Мне кажется, надо просто написать хранимую процедуру. Все описанные действия реализуются в ХП.
Работать с SQL сервером через TTable - это переносить логику xBase & Paradox, т.е. файл-серверных платформ на SQL, что не есть правильно. Вообще-то, бизнес логика приложения на SQL платформе должна танцевать от запросов и хранимых процедур а не TTablов.
← →
Johnmen © (2004-04-22 10:30) [18]Казалось бы, причём здесь TTable ?
:)
← →
Sergey13 © (2004-04-22 11:00) [19]2kalliopiy
Поставь перед
divisionsDS.Append;
showmessage или отладчиком посмотри firmsDS.FieldByName("id").
Может ошибка где то в другом месте кода если один раз проходит, а другой нет.
2Johnmen © (22.04.04 10:30) [18]
>Казалось бы, причём здесь TTable ?
>:)
Зато как мощно задвинул. Особенно про SQL платформу. 8-)
Страницы: 1 вся ветка
Текущий архив: 2004.05.16;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.036 c