Конференция "Базы" » Запись данных сразу в несколько таблиц [D7, MySQL]
 
  • AnacRon © (15.02.11 20:48) [0]
    Доброго всем времени суток!
    Уже устал бегать по всем закаулкам инета и документации и решил спросить.
    Сам я не силен в программировании (чайник   ), но встала задача, которую необходимо решить.
    дано: Object pascal (дргим не владею), 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;


    суть вопроса: Читаю все это по некоторым причинам не через на прямую в объект на конкретную запись журнала. Таких объектов может считаться сразу несколько с разных клиентских машин.
    Данные из таблицы 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 (вставка, редактирование, удаление). И ни как не могу придумать чтобы записать эти изменения в таблицу (вставка, редактирование, удаление) т.к. считанные и измененные объекты могут сохраняться в разные периоды и с разных машин.
    Если вопрос совсем детский то прошу прощения. и пните в нужную сторону! уже несколько вариантов испробовал убил целую неделю но так и не разработал нужный алгоритм.
  • KilkennyCat © (15.02.11 23:47) [1]

    > (вставка, редактирование, удаление) т.к. считанные и измененные
    > объекты могут сохраняться в разные периоды и с разных машин.
    >

    ты имеешь ввиду, как избежать ситуацию, типа: когда один клиент запись удалил, а второй ее изменил?
  • Гость (16.02.11 09:11) [2]

    > Читаю все это по некоторым причинам не через на прямую в
    > объект на конкретную запись журнала.

    честно, не понял
    >> все сообщения в форуме должны быть на русском языке

    если суть в
    >>как избежать ситуацию, типа: когда один клиент запись удалил, а второй ее изменил?

    то можно сделать так:
    Запись не удаляется, а в таблицах заводится поле IS_DELETED и ставит в true при удалении, соответственно такие записи не показываются потом. Но! их можно изменять. Только при update ставить проверку на поле IS_DELETED и предупреждать, что запись вообще-то удаленная.  А по логу, если ведется, а если нет - то вести, можно поднять кем и когда. И можно восстановить запись при выполнении update, если права юзера и бизнес-правила позволяют.
  • MsGuns © (16.02.11 10:43) [3]
    >Гость   (16.02.11 09:11) [2]

    Не надо советовать ерунду
  • Гость (16.02.11 10:55) [4]
    MsGuns ©   (16.02.11 10:43) [3]
    что именно?

    и осталось сказать более чем 5ти разработчикам известных в России программ, с коими доводилось работать, в т.ч. http://www.sbscorp.ru/ и http://www.servplus.ru/branches/tradeauto/supermag/supermag_step_by_step/
    что они делают по ерундовым принципам
  • MsGuns © (16.02.11 12:41) [5]
    >Гость   (16.02.11 10:55) [4]
    >что именно?

    Попытки "заведения" специальных полей, где должны отмечаться блокировки записей. Бо это неминуемо заведет в могилу.
    Делать это (предотвращать коллизии между пользователями, например, используя механизи блокировок) нужно исключительно средствами СУБД, а если таковых не имеется (не знаю постгрес), то соответственно продумывать интерфейс (с помощью трехзвенки например)

    На этом ресурсе туча конференций на эту тему
  • MsGuns © (16.02.11 12:47) [6]
    И еще мертвичина - это "условно" удаленные записи. Превносит путаницу и неразбериху в работе юзверей и перманентую головную боль администратору БД.
    Восстановление "убитых" записей борется штатными средствами:
    - тактическими через рестор базы
    - стратегически через порку виновного розгами с последующим заставлением оного повторно ввести документ. Через некоторое время товарысч перейдет на работу по принципу "7 раз проверь - один раз удали"
  • MsGuns © (16.02.11 12:52) [7]
    И последнее
    Ежели программа построена по принципу "записей", то в топку такую программу не смотря на красивые рюшечки и окошечки. Нормальные "взрослые" программы оперируют объектами: документами, операциями, ТМЦ, проводками и т.д. "Просто так" объекты не удаляют, для этого должно быть основание - это раз. Все удаления (итзменения, вставки) автоматически должны заноситься в логи, кои и просматриваются в случае "разбора полетов"

    Придумывать велосипеды с шестеренчатыми колесами и тремя рулями может и интересно кому-то, но неблагодарно. Как минимум
  • Гость (16.02.11 13:02) [8]
    2 MsGuns ©

    Гость   (16.02.11 10:55) [4] было к чему:
    К тому, что сделать как с технологией 1с, документ проведен или непроведен. (влияет или нет на остатки). Не тот же ли это признак удален или не удален, только с иной точки зрения?

    >> "условно" удаленные записи. Превносит путаницу и неразбериху в работе юзверей и перманентую головную боль администратору БД.
    это да. это согласен. и программировать намного сложнее. но ведь и гибче

    >> туча конференций на эту тему
    да-да, и на других тоже много

    "условно" удаленные записи все равно нужны,
    ну можно назвать иначе, как архив, корзина ну и прочие слова. Только суть все равно не меняется. В многоссылочной БД порой невозможно удалить без ТАКОГО каскадного удаления, что при малейшей ошибке потом не соберешь концы
  • clickmaker © (16.02.11 13:19) [9]
    > В многоссылочной БД порой невозможно удалить без ТАКОГО
    > каскадного удаления

    логику надо не на каскадных триггерах строить, а выносить в хранимки, например. А иначе и правда концов не найдешь


    > "условно" удаленные записи все равно нужны

    для архивов лучше отдельные таблицы заводить
  • Anatoly Podgoretsky © (16.02.11 13:41) [10]
    > Гость  (16.02.2011 13:02:08)  [8]

    1С это пример как не надо делать.
  • Гость (16.02.11 14:20) [11]
    2 Anatoly Podgoretsky ©   (16.02.11 13:41) [10]
    сам не люблю :-|)
    а все сидят в ней. Как, извинения прошу, презерватив. Никто не любит, а все юзают

    2 clickmaker ©   (16.02.11 13:19) [9]
    >>логику надо не на каскадных триггерах строить, а выносить в хранимки, например. А иначе и правда концов не найдешь
    не всегда получается.
    потом как вспомнят что-то.. ну и выбор: или 80% переписывать или триггер.

    >>для архивов лучше отдельные таблицы заводить
    чем лучше?
    партицирование (или ключ) навесить на признак deleted и нормально
  • clickmaker © (16.02.11 14:56) [12]
    > >>для архивов лучше отдельные таблицы заводить
    > чем лучше?

    тем что отдельно и не надо "партицирование (или ключ) навесить на признак deleted".
    поиск по архиву, как правило, в разы, а то и на порядок реже, чем по живым таблицам. Нафига баласт на борту держать?
  • MsGuns © (16.02.11 16:13) [13]
    >clickmaker ©  

    Он (Гость), как кот Васька, читает, но делает по своему.
    Его вряд ли переубедить :)
  • AnacRon © (16.02.11 21:36) [14]
    Всех благодарю за мнения!

    > сам не люблю :-|)
    > а все сидят в ней. Как, извинения прошу, презерватив. Никто
    > не любит, а все юзают

    вопрос рекламы. и не образованности пользователя.
  • DiamondShark © (17.02.11 10:58) [15]

    > MsGuns ©   (16.02.11 12:41) [5]
    > MsGuns ©   (16.02.11 12:47) [6]
    > MsGuns ©   (16.02.11 12:52) [7]


    "Не надо советовать ерунду" (Ц)
  • MsGuns © (17.02.11 15:51) [16]
    >DiamondShark ©   (17.02.11 10:58) [15]

    Посмеялсо. Пасибки
  • DiamondShark © (17.02.11 18:08) [17]

    > MsGuns ©   (17.02.11 15:51) [16]

    Давай посмеёмся вместе.

    [5]
    Есть простейшая база данных из одной таблицы:
    CREATE TABLE Entity(
    ID int not null identity(1,1) primary key,
    Name varchar(256) not null
    )

    С тебя два примера приложения для просмотра, ввода и модификации этой информации с предотвращением коллизий.
    Первый -- средствами СУБД
    Второй -- продуманным интерфейсом (с помощью трехзвенки например)

    [6]

    В предыдущий пример вносится небольшое расширение.

    CREATE TABLE EntityFacts(
    ID int not null identity(1,1) primary key,
    Entity int not null,
    FactDate datetime not null,
    FactInfo TFactInfo not null,
    CONSTRAINT FK_Entity FOREIGN KEY(Entity) REFERENCING Entity(ID)
    )

    Сбором фактов занимаются мобильные агенты, не имеющие постоянного подключения к центральной базе.

    С тебя:
    - пример приложения без коллизий и без каких либо дополнительных флагов.
    - инструкция для оператора центральной базы с чёткими указаниями, какие записи из Entity он не имеет права удалять или модифицировать.

    [7]

    С тебя версии приложений из предыдущих пунктов, только с объектами, без каких-либо манипуляций с записями.
 
Конференция "Базы" » Запись данных сразу в несколько таблиц [D7, MySQL]
Есть новые Нет новых   [134431   +16][b:0][p:0.002]