Поиск:

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


Новичок



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

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



Доброго всем времени суток!
Уже устал бегать по всем закаулкам инета и документации и решил спросить.
Сам я не силен в программировании (чайник   ), но встала задача, которую необходимо решить.
дано: Object pascal (fpc, delphi), mysql (postgresql, sqlite).
имеем: несколько таблиц, одна из которых главная и представляет из себя список (журнал событий и т.п.):
Код

CREATE TABLE `first` (
    `id` INT(6) NOT NULL AUTO_INCREMENT,
    `num` INT(9) NULL DEFAULT NULL,
    `desc` VARCHAR(20) NULL DEFAULT NULL,
    `data` DATE NULL DEFAULT NULL,
    `comment` VARCHAR(150) NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `num` (`num`)
)

и несколько таблиц такого характера (параметры привязанных к списку предыдущей таблицы):
Код

CREATE TABLE `second` (
    `id` INT(6) NOT NULL AUTO_INCREMENT,
    `num` INT(9) NULL DEFAULT NULL,
    `cnt` INT(9) NULL DEFAULT NULL,
    `par1` VARCHAR(120) NULL DEFAULT NULL,
    `par2` DECIMAL(11,3) NOT NULL,
    `par3` INT(2) NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `cnt` (`cnt`, `num`, `par1`)
)

в коде: классы для работы с этими данными. Первая таблица 
Код

  TSecond = class //таблица с параметрами
  private
    Fid  : integer;
    Fnum  : string;  // номер записи в журнале по которому происходит выборка строк с параметрами 
                     // SELECT s.id, s.cnt, s.par1, s.par2, s.par3 FROM first f, second s WHERE s.num=f.num
    Fcnt  : string;
    Fpar1  : string;
    Fpar2  : double;
    Fpar3  : integer;
  public
    constructor Create; overload;
  published
    property id  : integer read Fid write Fid;
    property num  : string read Fnum write Fnum;
    property cnt  : string read Fcnt write Fcnt;
    property par1  : string read Fpar1 write Fnam1;
    property par2  : double read Fpar2 write Fpar2;
    property par3  : integer read Fpar3 write Fpar3;
  end;

  TFirst = class (TObject) // таблица списка (журнала)
  private
    Fnum  : string;
    Fdesc  : string;
    Fdata  : TDateTime;
    Fcomment  : string;
    FItems: TList;
    function GetItems(Row: integer): TSecond;
    procedure SetItems(Row: integer; const AValue: TSecond);
  public
    property Items[Row: integer]: TSecond read GetItems write SetItems;
    constructor Create; overload;
    destructor Destroy; override;
    function AddItem(item: TSecond): integer;
  published
    property num  : string read Fnum write Fnum;
    property dat  : TDateTime read Fdat write Fdat;
    property Tip  : boolean read FTip write FTip;
    property Itog  : double read FItog write FItog;
  end;


суть вопроса: Читаю все это по некоторым причинам не через dataset, а на прямую в объект на конкретную запись журнала. Таких объектов может считаться сразу несколько с разных клиентских машин. 
Данные из таблицы Second хранятся в TFirst.Items;
Код

...
mySecond := TSecond.Create;
with SQLQuery of
try
  SQL.Text := 'SELECT s.id, s.cnt, s.par1, s.par2, s.par3 FROM first f, second s WHERE s.num=f.num;';
  Open;
  mySecond.id := FieldByName('id').AsInteger;
  mySecond.cnt := FieldByName('cnt').AsString;
  mySecond.par1 := FieldByName('par1').AsString;
  mySecond.par2 := FieldByName('par2').AsString;
  mySecond.par3 := FieldByName('par3').AsString;
  Close; 
except
end;
myFirst.AddItem(mySecond);
...


Затем возможны изменения в этом самом Items (вставка, редактирование, удаление). И ни как не могу придумать чтобы записать эти изменения в таблицу (вставка, редактирование, удаление) т.к. считанные и измененные объекты могут сохраняться в разные периоды и с разных машин.
Если вопрос совсем детский то прошу прощения. и пните в нужную сторону! уже несколько вариантов испробовал убил целую неделю но так и не разработал нужный алгоритм.

Это сообщение отредактировал(а) AnacRon - 17.2.2011, 09:08
PM   Вверх
Antimol
Дата 15.2.2011, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Первое что приходи в голову: перебор всех записей и проверка на удаление/редактирование/добавление. Если изменения были - вносим их
--------------------
Лучшее спасибо это "+" к репутации.   Мой блог: ИНФОРМАТИЗАЦИЯ, и mirsovetov.net. Написание программ, исправление ошибок, статьи....
PM MAIL WWW ICQ   Вверх
chip_and_dayl
Дата 15.2.2011, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



На данный момент у самого такая задача smile

В любом случае нужно пробежаться по списку и формировать  запрос типа для случая

а)
если mySecond.id=null или ноль, то беж запись  была создана пользователем
то делаем инсерт записи

б)
если mySecond.id<>null или нулю то делаем апдейт

Тут правда не понятно как отслеживается удаление

По поводу апдейта, может выйти, что запись уже удалили, тогда еще перед апдейтом делать проверку,  чтобы предупредить пользоватедя

В итоге пробежавшись по всем элементам  списка должно выйти следующий запрос:

insert into Second (p1, p2)  Value(1,2)
insert into Second (p1, p2)  Value(7,5)
update Second set p1=1, p2=4 where ID=4
и
т.д.


--------------------
Фсё будет хорошо!!!
PM MAIL Skype   Вверх
AnacRon
Дата 15.2.2011, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Так же проскакивала мысль о генерации запросов по конкретному действию в объекте, но сразу возникает нагрузка на сервер. К примеру если не сильно грамотный пользователь будет по неуверенности жать все подряд то может получиться что-то типа
Код

INSERT ... ON DUBLICATE UPDATE ...
DELETE ...
INSERT ... ON DUBLICATE UPDATE ...
DELETE ...
INSERT ... ON DUBLICATE UPDATE ...
INSERT ... ON DUBLICATE UPDATE ...
INSERT ... ON DUBLICATE UPDATE ...
DELETE ...
DELETE ...
INSERT ... ON DUBLICATE UPDATE ...
DELETE ...
INSERT ... ON DUBLICATE UPDATE ...

хотя на деле было всего-то добавлено 2 строки в БД. а что будет если таких действий над Second будет пару десятков, а одновременно работа идет наl с сотнями объектов myFirst.

из всех вариантов, что мне приходило и в голову и в то место, через которое вышла эта задача, сам решил удалять по id  поля таблицы Second, id  придется хранить  где-то в объекте программы
Код

DELETE FROM second WHERE id=n OR id=n1 OR id=n2......

и затем выполнять 
Код

INSERT ... ON DUBLICATE UPDATE ...
 для оставшихся данных. Более логичного способа пока не вижу.
Если честно, то я надеялся, что может существовать более логичный и красивый способ решения, но пока найти его я не смог

Это сообщение отредактировал(а) AnacRon - 15.2.2011, 21:14
PM   Вверх
chip_and_dayl
Дата 15.2.2011, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(AnacRon @  15.2.2011,  21:10 Найти цитируемый пост)
К примеру если не сильно грамотный пользователь будет по неуверенности жать все подряд то может получиться что-то типа

Если пользователь создал запись и удалил, то в списке этого элемента не должно быть. И когда мы будем объект сохранять в базу, то мы будем видеть то что есть.

Плюс для объекта нужно свойство УДАЛЕН, если элемент был создан (и сохранен в базе) и пользователь удалил

Добавлено через 3 минуты и 22 секунды
А ид нужно хранить в любом случае, без него никак, при апдейте и удаление  smile



Код

Если честно, то я надеялся, что может существовать более логичный и красивый способ решения, но пока найти его я не смог

Пока еще не придумали smile

Это сообщение отредактировал(а) chip_and_dayl - 15.2.2011, 22:21


--------------------
Фсё будет хорошо!!!
PM MAIL Skype   Вверх
Vas
Дата 16.2.2011, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 29.6.2005
Где: Stavropol region

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



А вот интересно, если пользователь, не открыл объект, а создал и должен добавить в БД, другой пользователь может в это время добавить точно такой же объект или нет?

Что-то мне кажется что все значительно проще, или я не понимаю до конца задачу. В объект добавляем поля которые заполняем при открытии объекта и ставим их в ReadOnly. А правим те что есть, то бишь получается дубляж полей ( ну и хрен с ним). 
Перед сохранением ищем запись с полями из свойств ReadOnly и смотрим есть или нет, если есть значит ее никто не менял и мы смело сохраняем по Update, если нет и свойства не пустые до предупреждаем пользователя что кто-то ее сменил, пока он сидел "ворон считал". Ну и предлагаем посмотреть изменения и оставить те что есть или сохранить свои, опять просто Update.

Если свойства объекта со статусом ReadOnly пустые, то значит пользователь создал объект, его надо просто сохранить в БД по Insert. А тут как раз возникает мной заданный вопрос в начале поста.

Добавлено через 1 минуту и 43 секунды
Цитата(AnacRon @  15.2.2011,  13:30 Найти цитируемый пост)
т.к. считанные и измененные объекты могут сохраняться в разные периоды и с разных машин.

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


--------------------
И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель. ... (А.С. Пушкин)
PM MAIL   Вверх
AnacRon
Дата 16.2.2011, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Vas @ 16.2.2011,  09:08)
Если свойства объекта со статусом ReadOnly пустые, то значит пользователь создал объект, его надо просто сохранить в БД по Insert.

на деле так и реализовано.
Цитата(Vas @ 16.2.2011,  09:08)
ID у них должен быть постоянен и никогда не меняться, иначе получите полную кашу.

так это и понятно. autoincrement стоит не зря у этого поля
Цитата(Vas @ 16.2.2011,  09:08)
А вот интересно, если пользователь, не открыл объект, а создал и должен добавить в БД, другой пользователь может в это время добавить точно такой же объект или нет?

Перед сохранением в БД всегда можно в транзакции  опросить максимальный ID и сохранить отличным от него на 1. При условии, что БД поддерживает эти самые транзакции. Или я не прав?
PM   Вверх
chip_and_dayl
Дата 16.2.2011, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(AnacRon @  16.2.2011,  20:52 Найти цитируемый пост)
Перед сохранением в БД всегда можно в транзакции  опросить максимальный ID и сохранить отличным от него на 1. При условии, что БД поддерживает эти самые транзакции. Или я не прав?

А зачем? Если поле ИД инкрементное и мы не передаем. СУБД сама его назначает


--------------------
Фсё будет хорошо!!!
PM MAIL Skype   Вверх
Deniz
Дата 17.2.2011, 08:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

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



Цитата(AnacRon @  15.2.2011,  15:30 Найти цитируемый пост)
Читаю все это по некоторым причинам не через на прямую в объект на конкретную запись журнала.
Не совсем понял о чем речь, вероятно не в dataset, а в свой объект?
Можно озвучить эти причины?

Цитата(AnacRon @  15.2.2011,  23:10 Найти цитируемый пост)
ак же проскакивала мысль о генерации запросов по конкретному действию в объекте, но сразу возникает нагрузка на сервер.
т.е. это основная причина?
Для похожих действий есть механизм кешированных изменений.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
AnacRon
Дата 17.2.2011, 09:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Deniz @ 17.2.2011,  08:16)
Не совсем понял о чем речь, вероятно не в dataset, а в свой объект?
Можно озвучить эти причины?

Да именно так, не в dataset! прошу прощения за опечатку. Причина: слабый пропускной канал. постоянно перегруженный сервер. По расчетам нашего админа, разовый запрос мене напрягает сеть и сервер чем работа с dataset`ами. Я начинающий программист, по этому пока верю на слово, не разобравшись пока с этим на практике.

Цитата(Deniz @ 17.2.2011,  08:16)
Цитата(AnacRon @  15.2.2011,  23:10 Найти цитируемый пост)
ак же проскакивала мысль о генерации запросов по конкретному действию в объекте, но сразу возникает нагрузка на сервер.
т.е. это основная причина?

если есть вариант более экономичный в ресурсах почему им не воспользоваться? 

PM   Вверх
Vas
Дата 17.2.2011, 09:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 830
Регистрация: 29.6.2005
Где: Stavropol region

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



Цитата(AnacRon @  17.2.2011,  09:06 Найти цитируемый пост)
Причина: слабый пропускной канал. постоянно перегруженный сервер. По расчетам нашего админа, разовый запрос мене напрягает сеть и сервер чем работа с dataset`ами. Я начинающий программист, по этому пока верю на слово, не разобравшись пока с этим на практике.

Дык выбирай в датасет одну строку, и нагрузка будет одинаковая, что в объект потом запихивать, что работать с датасетом.


--------------------
И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель. ... (А.С. Пушкин)
PM MAIL   Вверх
Deniz
Дата 17.2.2011, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1251
Регистрация: 16.10.2004
Где: Новый Уренгой

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



Повторюсь:
Цитата(Deniz @  17.2.2011,  10:16 Найти цитируемый пост)
Для похожих действий есть механизм кешированных изменений. 

можно использовать почти трехзвенку, сервер приложений и клиент в одном флаконе.
В двух словах:
1. Клиент через провайдер выбирает в ClientDataSet все необходимые записи и отключается от сервера.
2. Далее проводится необходимая обработка данных.
3. Если связи с сервером нет, можно временно сохранить в локальный файл, и перезагрузить комп.
4. После перезагрузки данные подгрузить в программу из локального файла.
5. После появления соединения (желания пользователя сохранить), дельту изменений можно отправить на сервер.
Шаги 3 и 4 можно по желанию пропустить.


--------------------
"Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с)
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

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

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


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

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

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


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

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


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

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


 




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


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

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