C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Посоветуйте., сохр.записей из mster-detail табл
Миshук
Отправлено: 18.10.2006, 12:35


Дежурный стрелочник

Группа: Участник
Сообщений: 36



Приветствую. (ADO+ MS SQL 2000)
опыт разработки приложений для работы с БД маленький. До этого использовал простые — одна большая таблица и справочники. Сейчас есть БД с несколькими связанными таблицами. две из них имеют структуры:
главная таблица (табл1):
1 поле: PacientID — int — автоинкриментное (искуственный ключ)
2 поле ............
..........

подчиненная таблица(табл2):
1 поле: ID — int — автоинкриментное(искуственный ключ)
2 поле: PacientID — int -
3 поле: Factors


обе таблицы связаны по полю PacientID. Т.е одной записи в таблице 1 одновременно может соответствовать несколько записей таблицы табл2. В свойствах связи стоит каскадное удаление записей из подчиненной таблицы.
так вот, есть форма с контролами. где-то посреди формы я должен внести данные(несколько записей),которыми заполняется подчиненная таблица, а потом дальше продолжать заполнять контролы, которые связаны с главной таблицей. Проблема состоит в том, что я не могу вставлять записи в подчиненную таблицу, пока не сделаю Post главной(все из- за автоинкрементного поля). а именно такой подход мне и нужен т.е. сначала заполняю часть контролов связ-ых с глав.табл. потом вставляю записи в подчинен.табл. а потом продолжаю заполнять контролы связ-ые с гл.табл. В итоге получается одна запись в главной таблице и несколько записей соответсвующих ей в подчиненной таблице. (что-то растянул, короче 1:n)
Поскажите пожалуйста чем разрулить это. Может явными транзакциями, может какими-нибудь временными таблицами? сначала вставлять записи котроые должны содержаться в подчиненной таблице во временную, а потом после поста главной таблицы сливать их из временной в подчиненную. А может какие компаненты есть сторонние?

Вроде в EhLib есть то что мне надо, но ей пока совсем не пользовался. попробовал бы, но обстоят-ва сложились так, что делаю проект на Делфе7 а EhLib не хочет туда вставать — пакеты даже не компилятся. поэтому может есть варианты без EhLib? Спасибо!
olegenty
Отправлено: 18.10.2006, 12:43


Ветеран

Группа: Модератор
Сообщений: 2412



попробуй поигаться с TClientDataSet + CachedUpdates=true;

на sql.ru есть участник — pkarklin, он реализовал то, что тебе требуется, именно таким способом. можешь с ним списаться.
AVC
Отправлено: 18.10.2006, 14:28


Ветеран

Группа: Модератор
Сообщений: 1583



Еше вариант — создаем главную запись с минимально необходимым заполнением полей (как минимум ID). Потом вставляем подчиненные. Потом заполняем остальные поля основной.
Все это дело еще можно обернуть в одну транзакцию.

Или как сказал olegenty — все необходимые записи формируем на клиенте а потом, при сохранении на сервере, достраиваем все записи до требуемого состояния (та же транзакция, но на клиенте:) ).
olegenty
Отправлено: 18.10.2006, 14:32


Ветеран

Группа: Модератор
Сообщений: 2412



да, как говорит AVC, pkarklin сделал это в управляемой с клиента транзакции.

есть ещё вариант: пихаем новьё в XML, XML отдаём хранимой процедуре, она его разбирает и делает всё, что требуется. MSSQL обладает встроенными средствами разбора XML.
Миshук
Отправлено: 30.10.2006, 11:47


Дежурный стрелочник

Группа: Участник
Сообщений: 36



Привет!
QUOTE
есть ещё вариант: пихаем новьё в XML, XML отдаём хранимой процедуре, она его разбирает и делает всё, что требуется. MSSQL обладает встроенными средствами разбора XML.

до этого кажеться вообще еще не дорос.smile.gif
А вот на счет
QUOTE
Еше вариант — создаем главную запись с минимально необходимым заполнением полей (как минимум ID). Потом вставляем подчиненные. Потом заполняем остальные поля основной.

Что-то не получается.может я чего не допонимаю. а конкретенее — в XMLке главной таблицы(да и подчиненной) при сохранении записи
QUOTE
с минимально необходимым заполнением полей (как минимум ID)
не формируется автоинкрементное поле. Оно появляется только в базе после посылки данных в базу.ну это вроде и как естественно — так думаю СУБД должна формировать автоинкрементное значение. ну а зачем мне тогда формировать записи на клиенте без автоинкрементного значения?

правильно ли я делаю?
к примеру:
CODE

/// создаю XML файл ....
ClientDataSet->Open();
ClientDataSet->Insert();
.......заполняю какие-то минимально необходимые поля
ClientDataSet->Post();
ну и потом
ClientDataSet->ApplyUpdate(-1);
.........

ну и сохранение и передача изменений в базу заворачиваю в транзакцию на клиенте.
Короче, наругайте меня если что-то не так!

Отредактировано Миshук — 30.10.2006, 12:50
olegenty
Отправлено: 30.10.2006, 12:10


Ветеран

Группа: Модератор
Сообщений: 2412



и тем не менее XML — это просто.

всего-то

sp_xml_preparedocument
sp_xml_removedocument
OPENXML
Миshук
Отправлено: 30.10.2006, 17:05


Дежурный стрелочник

Группа: Участник
Сообщений: 36



Привет!
QUOTE
и тем не менее XML — это просто.
Хорошо,покавыряюсь!
Но тем не менее, smile.gifа как вы осуществляете сохранение записей в master-detail таблицах в многопользовательских приложениях? Спасибо!

P.S. А может таблицы спроектированы неправильно? Да вроде нет!
AVC
Отправлено: 31.10.2006, 10:00


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (Миshук @ 30.10.2006, 17:05)
как вы осуществляете сохранение записей в master-detail таблицах в многопользовательских приложениях?

Зависит от СУБД, но основная проблема состоит в получении PK основной записи до создания подчиненных. Для этого можно применить вызов генератора если автоинкремент построен на генераторе или фразу returning команды insert если позволяет синтаксис или, если есть такое — значение глобальной переменной @@identity или, в конце концов, имитатор генератора на SP.
Все вставки обернуты в транзакцию.
olegenty
Отправлено: 31.10.2006, 10:27


Ветеран

Группа: Модератор
Сообщений: 2412



у меня такое бывает только по окончании работы визардов. на сервер уходит XML. сервер его разбирает и раскладывает по временным таблицам. дальше всё стандартно.
Миshук
Отправлено: 03.11.2006, 09:48


Дежурный стрелочник

Группа: Участник
Сообщений: 36



Привет!
Вообщем, я сам не понял зачем я прицепился к XML и создавал локальный файл на машине(портфельный набор), когда можно просто загрузить данные в ClientDataSet поработать с ними (в памяти) и отправить обратно в базу.
Короче,если кому интересно, при сохранении записи из мастер-детайл таблицы сначала как вы и говорили постю запись гл.таблицы (для нее клинтский набор не делал),потом значение ее автоинкрементного поля закидываю в детайл таблицу и ApplyUpdates'ом их в базу. Ну и все энтно акуратно заворачивается в транзакцию. После закрываю КлиентДатаСет, инсертю Основные наборы данных(главный и подчиненный),связанные между собой, и опять открываю КлиентДатаСет для подчиненного набора... и т.д. это что касается процедуры записи данных в базу данных. Всем спасибо!!!
olegenty
Отправлено: 03.11.2006, 10:15


Ветеран

Группа: Модератор
Сообщений: 2412



XML я никуда на диск не кладу, это строка, на выходе с визарда генерируется. Что-то типа:
CODE

<root>
   <record FakeOperationID="1" Name="Сборочная операция">
       <subrecord UnitIID="123123" Num="12.3"></subrecord>
       ...
   </record>
   ...
</root>

а MSSQL потом разбирает это и кладёт в таблицы.

Вернуться в Работа с базами данных в C++Builder