-
Доброго всем времени суток! Уже устал бегать по всем закаулкам инета и документации и решил спросить. Сам я не силен в программировании (чайник ), но встала задача, которую необходимо решить. дано: 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; 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 (вставка, редактирование, удаление). И ни как не могу придумать чтобы записать эти изменения в таблицу (вставка, редактирование, удаление) т.к. считанные и измененные объекты могут сохраняться в разные периоды и с разных машин. Если вопрос совсем детский то прошу прощения. и пните в нужную сторону! уже несколько вариантов испробовал убил целую неделю но так и не разработал нужный алгоритм.
-
> (вставка, редактирование, удаление) т.к. считанные и измененные > объекты могут сохраняться в разные периоды и с разных машин. >
ты имеешь ввиду, как избежать ситуацию, типа: когда один клиент запись удалил, а второй ее изменил?
-
> Читаю все это по некоторым причинам не через на прямую в > объект на конкретную запись журнала.
честно, не понял >> все сообщения в форуме должны быть на русском языке
если суть в >>как избежать ситуацию, типа: когда один клиент запись удалил, а второй ее изменил?
то можно сделать так: Запись не удаляется, а в таблицах заводится поле IS_DELETED и ставит в true при удалении, соответственно такие записи не показываются потом. Но! их можно изменять. Только при update ставить проверку на поле IS_DELETED и предупреждать, что запись вообще-то удаленная. А по логу, если ведется, а если нет - то вести, можно поднять кем и когда. И можно восстановить запись при выполнении update, если права юзера и бизнес-правила позволяют.
-
>Гость (16.02.11 09:11) [2]
Не надо советовать ерунду
-
-
>Гость (16.02.11 10:55) [4] >что именно?
Попытки "заведения" специальных полей, где должны отмечаться блокировки записей. Бо это неминуемо заведет в могилу. Делать это (предотвращать коллизии между пользователями, например, используя механизи блокировок) нужно исключительно средствами СУБД, а если таковых не имеется (не знаю постгрес), то соответственно продумывать интерфейс (с помощью трехзвенки например)
На этом ресурсе туча конференций на эту тему
-
И еще мертвичина - это "условно" удаленные записи. Превносит путаницу и неразбериху в работе юзверей и перманентую головную боль администратору БД. Восстановление "убитых" записей борется штатными средствами: - тактическими через рестор базы - стратегически через порку виновного розгами с последующим заставлением оного повторно ввести документ. Через некоторое время товарысч перейдет на работу по принципу "7 раз проверь - один раз удали"
-
И последнее Ежели программа построена по принципу "записей", то в топку такую программу не смотря на красивые рюшечки и окошечки. Нормальные "взрослые" программы оперируют объектами: документами, операциями, ТМЦ, проводками и т.д. "Просто так" объекты не удаляют, для этого должно быть основание - это раз. Все удаления (итзменения, вставки) автоматически должны заноситься в логи, кои и просматриваются в случае "разбора полетов"
Придумывать велосипеды с шестеренчатыми колесами и тремя рулями может и интересно кому-то, но неблагодарно. Как минимум
-
2 MsGuns ©
Гость (16.02.11 10:55) [4] было к чему: К тому, что сделать как с технологией 1с, документ проведен или непроведен. (влияет или нет на остатки). Не тот же ли это признак удален или не удален, только с иной точки зрения?
>> "условно" удаленные записи. Превносит путаницу и неразбериху в работе юзверей и перманентую головную боль администратору БД. это да. это согласен. и программировать намного сложнее. но ведь и гибче
>> туча конференций на эту тему да-да, и на других тоже много
"условно" удаленные записи все равно нужны, ну можно назвать иначе, как архив, корзина ну и прочие слова. Только суть все равно не меняется. В многоссылочной БД порой невозможно удалить без ТАКОГО каскадного удаления, что при малейшей ошибке потом не соберешь концы
-
> В многоссылочной БД порой невозможно удалить без ТАКОГО > каскадного удаления
логику надо не на каскадных триггерах строить, а выносить в хранимки, например. А иначе и правда концов не найдешь
> "условно" удаленные записи все равно нужны
для архивов лучше отдельные таблицы заводить
-
> Гость (16.02.2011 13:02:08) [8]
1С это пример как не надо делать.
-
2 Anatoly Podgoretsky © (16.02.11 13:41) [10] сам не люблю :-|) а все сидят в ней. Как, извинения прошу, презерватив. Никто не любит, а все юзают
2 clickmaker © (16.02.11 13:19) [9] >>логику надо не на каскадных триггерах строить, а выносить в хранимки, например. А иначе и правда концов не найдешь не всегда получается. потом как вспомнят что-то.. ну и выбор: или 80% переписывать или триггер.
>>для архивов лучше отдельные таблицы заводить чем лучше? партицирование (или ключ) навесить на признак deleted и нормально
-
> >>для архивов лучше отдельные таблицы заводить > чем лучше?
тем что отдельно и не надо "партицирование (или ключ) навесить на признак deleted". поиск по архиву, как правило, в разы, а то и на порядок реже, чем по живым таблицам. Нафига баласт на борту держать?
-
>clickmaker ©
Он (Гость), как кот Васька, читает, но делает по своему. Его вряд ли переубедить :)
-
Всех благодарю за мнения!
> сам не люблю :-|) > а все сидят в ней. Как, извинения прошу, презерватив. Никто > не любит, а все юзают
вопрос рекламы. и не образованности пользователя.
-
> MsGuns © (16.02.11 12:41) [5] > MsGuns © (16.02.11 12:47) [6] > MsGuns © (16.02.11 12:52) [7]
"Не надо советовать ерунду" (Ц)
-
>DiamondShark © (17.02.11 10:58) [15]
Посмеялсо. Пасибки
-
> 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]
С тебя версии приложений из предыдущих пунктов, только с объектами, без каких-либо манипуляций с записями.
|