![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как пробежаться по строкам DBMemo? [D7, XP]
azamatufa © (2010-07-05 09:52:00)Есть FireBird, Delphi7, TIBDataSet в нем DBMemo поле.
Хочу в это Мемо содержать строки такого формата:
--------------------------------
2004-2005 | менеджер ООО Феникс
2005-2006 | складовщик ЗАО Пупкин
2006-2007 | зам.директора ОАО МММ
--------------------------------
т.е. трудовая деятельность человека, где "|" - разделитель.
Так, я должен писать и читать от туда.
Спасибо!
azamatufa (2010-07-09 07:22:00) [1]Еще раз, спасибо за Ваш опыт!
Юрий Зотов (2010-07-07 07:35:00) [2]
> azamatufa © (06.07.10 09:26) [27]
Вопросы 1 и 2: непринципиально, как удобнее - так и делайте. Можно, например делать и так - вместо поля Prev_ID ввести поле "счетчик", а первичным ключом задать сочетание полей ID и Счетчик. Тогда получится что-то типа этого:
ID Счетчик Имя Отчество
1 0 Вера Петровна
1 1 Мария Петровна
1 2 Иван Иваныч
Тогда ID идентифицирует самого человека, а счетчик - номера относящихся к нему записей. Действующая запись имеет максимальное значение счетчика.
Вопрос 3: Вы сами на него уже ответили - ключ должен содержать ID филиала, тогда повторов не будет. Главное тут не это, а вот что.
Допустим, в филиале сделали запись в некую таблицу. Потом провели слив в центральную базу и там эта запись тоже появилась. Сразу возникают вопросы, требующие решения:
а). кто имеет право видеть эту запись (внесший филиал, центр, все филиалы и т.п.)?
б). в последнем случае - как обновить БД других филиалов (там же тоже эта запись должна появиться)?
в). кто имеет право изменять/удалять эту запись (внесший филиал, центр, все филиалы и т.п.)?
г). при модификации/удалении записи - как обновить БД других филиалов (там же тоже эта запись должна измениться/удалиться)?
===========================
Лет 5-6 назад довелось мне делать именно такую распределенную БД, и филиалов тоже было примерно как у Вас. Главной проблемой оказалась именно синхронизация БД (репликация) с учетом прав доступа - особенно, из-за того, что записи могли быть дочерними и родительскими. Например.
1. Филиал Ф1 внес родительскую запись РЗ и дочернюю к ней ДЗ. Дочерняя запись, естественно, ссылается на родительскую.
2. Филиал Ф2 должен видеть запись ДЗ, но ни при каких условиях не должен видеть записи РЗ. То есть, записи РЗ в БД филиала Ф2 просто не должно быть - и тогда в записи ДЗ в БД филиала Ф2 появляется битая ссылка. Нарушение ссылочной целостности, ни больше, ни меньше - и, тем не менее, все обязано работать.
Для решения в каждой БД был заведен журнал изменений (состоял из несколькких таблиц) и написан специальный модуль репликаций. В журнале каждого филиала фиксируются все изменения, сделанные филиалом в его БД, затем эти изменения выгружаются на диск в виде XML. Этот XML проигрывается в центральную БД и формируется другой XML. Получив его, все филиалы соответственно обновляют свои БД, а филиал-источник очищает ставшие ненужными записи в своем журнале изменений.
Примерно так. Сразу скажу - хотя все это и работало, но геморроя при разработке и последующем вылавливании ошибок было выше крыши, уж больно хитрой оказалась логика репликаций. Поэтому лучше всего сразу убедить заказчика в том, что игра не стоит свеч и нужно делать так, как делают все нормальные люди - единую БД с разграничением прав доступа. Наш заказчик тогда настоял на своем, было угроблено куча времени и денег - а спустя некоторое время он сам понял, что был неправ и что ему самому работать с такой БД крайне неудобно. Но поздно - все было уже сделано, внедрено и им оплачено.
azamatufa (2010-07-06 09:26:00) [3]
> Юрий Зотов
Огромное спасибо за такой ответ!
Пару вопросов:
1. Вместо Prev_ID (который надо постоянно изменять) можно ведь постоянно тоскать с собой первоначальный ID (в поле Prev_ID) ? А хронологию по дате сечь...
ID Prev_ID Otchetstvo
1 1 Петровна
2 1 Николавна
3 1 Иванович (стал мужиком наконец) (End_Date - null)
2. В таблице должностных перемещений на какой ID_работника ссылаться? на первоначальный? или на последний актуальный..? (тоже вроде бы и так и так можно.. )
3. И еще больной вопрос: как правильно сливать данные от всех филиалов.. ведь ID'ы плывут... Мне кажется, надо в каждой таблице иметь поле Filial_ID...
и составной индекс Filial_ID + ID - например в таблица людей.
Спасибо!
p.s. Еще раз спасибо за отличные идеи и мысли! Я обязательно это возьму на вооружение!
Юрий Зотов (2010-07-05 16:53:00) [4]> azamatufa © (05.07.10 15:15) [23]
Во-первых, сразу же напрашивается отдельная таблица "Справочник филиалов" с полями ID (перв. ключ), Name (not null, unique) и любыми еще другими, какие нужны.
Вторая таблица - справочник должностей. Поля примерно те же - ID (перв. ключ), Name (not null, unique) и любые еще другие, какие нужны.
Третья таблица - справочник статусов (действующий, резервист, исключен и т.д.). Поля примерно те же.
Четвертая таблица - личные данные работников. Поля примерно такие:
ID (перв. ключ)
Prev_ID (ссылка на ID предыдущей записи в той же таблице; null означает, что эта запись первичная и предыдущей записи у нее нет)
Start_Date (дата начала действия записи, not null)
End_Date (дата окончания действия записи, null означает действующую)
Фамилия
Имя
Отчество
Пол
Дата рождения
и прочие редко изменяемые или совсем неизменяемые данные работников
Заметьте, что такая таблица может хранить не только текущие данные работника, но и всю историю их изменений. Например, она позволяет отследить, что нынешний Иван Иваныч пять лет назад сменил ФИО и пол, а до этого он был Марьей Петровной, а еще тремя годами раньше он был Верой Петровной.
Если нет отдельного справочника адресов (КЛАДР, например), то адрес нашего Иваныча тоже можно подстыковать в эту таблицу. После этого пусть он переезжает хоть каждый день - вся история его переездов тоже будет храниться. Как и смена номеров телефонов, если в эту же таблицу прицепить и телефон.
В общем, что хранить с историей, а что без нее - это решать Вам совместно с заказчиком.
Заметьте, что мы пока что ни слова не сказали о том, является ли наш Иваныч кадровым работником или резервистом, в каком филиале и на какой должности он работал, в какой период и и.п. Для этого мы сварганим еще одну, пятую таблицу - должностных перемещений. Примерно такую:
ID (перв. ключ)
Prev_ID (ссылка на ID предыдущей записи в той же таблице; null означает, что эта запись первичная и предыдущей записи у нее нет)
ID_филиала (ссылка на справочник филиалов)
ID_должности (ссылка на справочник должностей)
ID_статуса (ссылка на справочник статусов)
ID_работника (ссылка на первичную запись в таблице работников)
Start_Date (дата начала действия записи)
Номер_приказа_1 (на основании чего запись начала действовать)
End_Date (дата прекращения действия записи)
Номер_приказа_2 (на основании чего запись перестала действовать)
и т.п.
Заметьте, что эта таблица тоже хранит всю историю должностных перемещений - и наш Иваныч теперь как на ладони. Например, в любой момент мы можем определить, что в период с... по... он работал кладовщиком в филиале № 7 и получал 100 тыс. баксов в месяц. Причем в то время он был еще Петровной, а не Иванычем.
=============
Вот примерно в таком направлении я бы и думал - все ли необходимые данные мною охвачены; какие из них нужно хранить с историей, а какие нет; нельзя ли в этой схеме что-то упростить - и т.д.
Anatoly Podgoretsky (2010-07-05 15:33:00) [5]> azamatufa (05.07.2010 15:15:23) [23]
Это не сложно, достаточно добавить два поля - начало и конец действия
записи.
12 (2010-07-05 15:21:00) [6]> Может Вы сделаете срез "моих" желаний и дадите ЦУ в каком
> направлении думать дальше.....
Я не ЮЗ, но если бы я был ЮЗ, я бы направил читать теорию разработки БД
azamatufa (2010-07-05 15:15:00) [7]
> Юрий Зотов
Хорошо, уважаемый Юрий! Раз Вы хотите меня направить на путь истинный, позволю себе проконсультироваться у Вас и, конечно же, у не менее уважаемого All'a ;)
"Кадровая (узкопрофильная) программа".
Есть 40 филиалов. В каждом работает по 100 человек.
Раз в полгода (или чаще) они должны "выгружать" мне свои данные.
Каждый человек может "двигаться":
- быть действующим работником
- просто состоять в кадровом резерве
- быть действующим + состоять в кадровом резерве
- действующий/резервист может быть назначенным на должность (+ снова зачислиться в резерв)
- быть исключен из кадрового резерва
Чтоб сделать все по уму, как Вы сказали, надо предусмотреть "версионность" записей (историю).. а это (пока кажется что) сложно.... (((
Я (пока) выбрал вариант, когда идет конкретный дубляж данных:
отдельная таблица действующих
отдельная таблица резервистов
и т.п.
Может Вы сделаете срез "моих" желаний и дадите ЦУ в каком направлении думать дальше.....
Спасибо!
Юрий Зотов (2010-07-05 12:52:00) [8]Кстати, ИванИванычу никто не мешает сменить и фамилию, и даже имя. Вот тогда точно наступит капец, потому что для хранения истории изменений таблица не приспособлена.
Anatoly Podgoretsky (2010-07-05 12:21:00) [9]> azamatufa (05.07.2010 11:53:18) [18]
Не зарекайся, иначе придется вешаться, когда появится другая.
Anatoly Podgoretsky (2010-07-05 12:20:00) [10]> azamatufa (05.07.2010 11:15:15) [15]
Красиво печатать из базы данных, а не из мемо, и проще.
12 (2010-07-05 12:18:00) [11]SS:tstrings;
begin
memo1.Lines.Text := SS.Text
azamatufa (2010-07-05 11:53:00) [12]
> Юрий Зотов
Про нормальные формы я более менее слышал. В моем же случае тока одна запись про Иван Ивановича!
Гуру, подскажите как вогнать из TStrings в memo!
Юрий Зотов (2010-07-05 11:19:00) [13]А для красивой печати существуют отчеты.
Юрий Зотов (2010-07-05 11:19:00) [14]> azamatufa © (05.07.10 11:15) [15]
И сколько же строк в этой таблице будет соответствовать ОДНОМУ И ТОМУ ЖЕ ИванИванычу? Он ведь адрес, телефон и место работы может хоть каждый день менять.
azamatufa (2010-07-05 11:15:00) [15]
> Юрий Зотов
не уговаривайте)))
у меня по задумке одна табличка: Иванов,Иван,Иванович,муж,1962,место_работы,адрес,тел,трудовая_деятельность
"трудовая деятельность" - мог и просто TDBMemo, но хочу в последующем красиво печатать... поэтому и горожу огород....
azamatufa (2010-07-05 11:10:00) [16]Прошу прощения...
вот я считал так:
TrudMemo := TStream.Create;
TrudMemo := DM.Uchet_Card.CreateBlobStream(DM.Uchet_Card.FieldByName('TRUD_DEYAT'),bmRead);
TrudList := TStringList.Create;
TrudList.LoadFromStream(TrudMemo);
а как бы теперь записать из TStrings в блоб (т.е. обратно)?
Спасибо!
Юрий Зотов (2010-07-05 11:10:00) [17]> azamatufa © (05.07.10 10:43) [8]
> не охота еще одну таблицу делать для этого... (это про "еще проще")
А кто заставляет? Надо просто написать select, он соберет данные хоть из 100 разных таблиц - и не нужны никакие новые таблицы. А самый обычный DBGrig вполне успешно все это отобразит, без лишних телодвижений.
Anatoly Podgoretsky (2010-07-05 11:00:00) [18]> Anatoly Podgoretsky (05.07.2010 10:47:09) [9]
Не создавать DBMemo, а гнать потоком куда надо или превратить memo в string
azamatufa (2010-07-05 10:54:00) [19]TStream?
azamatufa (2010-07-05 10:50:00) [20]
> Anatoly Podgoretsky
а как? )))