Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Способ задания порядка записей [D6, AbsoluteDB]


Страницы:   1 2

Валигози2 ©   (2010-03-31 15:41:00) 

Подскажите пожалуйста какой-нибудь удобный способ задания порядка записей. Т.е. на форме лежит TDBGrid, но данные в нём должны отображаться не в порядке ввода, а в том порядке, в каком укажет пользователь (он может перемещать записи вверх/вниз с помощью соответствующих кнопок).
Единственное, что я смог придумать, это дополнительное поле в таблице типа INTEGER в котором и будет храниться порядково отображаемый номер и выбирать записи нужно с ORDER BY по этому полю. Но допустим поьзователь добавил 1000 записей и хочет сделать тысячную запись первой - тогда получается нужно обновтить все 1000 записей: в первое поле вместо 1 записать 1000, во второе вместо 2 записать 1, в третье вместо 3 записать 2 и т.д. :( Может есть способ получше?


MsGuns   (2010-04-03 22:40:00) [1]

По поводу секретности - это, как я понял, апрельский прикол ?
Не то чтобы смешно, но это такое..
Даю 90% что вы вообще это (в смысле перетаскивание с перенумерацией как вы их тут описали) не реализуете,
и 100%  что если все ж таки реализуете, никто больше месяца с этой прогой работать не будет ибо поумирают от инфарктов


Jeer   (2010-04-02 19:10:00) [2]


> Anatoly Podgoretsky ©   (02.04.10 18:01) [32]
>
> > Демо  (02.04.2010 15:44:30)  [30]
>
> Гениально


Это частное решение более общего, потому гениальность не замечена.
С учетом [33]  - все зависит от техники, СУБД, конкретного вида первичной таблицы ( стоит ли выносить sortorder в отдельную )


Демо   (2010-04-02 18:47:00) [3]


> Anatoly Podgoretsky ©   (02.04.10 18:01) [32]
> > Демо  (02.04.2010 15:44:30)  [30]Гениально


Ну какой-никай - выход.
Таблицу с одним неключевым полем проще обновить и быстрее.


Anatoly Podgoretsky   (2010-04-02 18:01:00) [4]

> Демо  (02.04.2010 15:44:30)  [30]

Гениально


Anatoly Podgoretsky   (2010-04-02 17:59:00) [5]

> Sergey13  (31.03.2010 16:10:01)  [1]

Он и так пойдет после первого использования.


Демо   (2010-04-02 15:44:00) [6]


> Валигози2   (31.03.10 15:41) 


Можно использовать такой вариант:
добавить ещё одну таблицу с двумя полями - Id,SortOrder, по Id связанную с основной и обновлять её для сортировки.
В-принципе, алгоритм достаточно простой при перемещении записей.


Anatoly Podgoretsky   (2010-04-02 15:24:00) [7]

> Валигози2  (02.04.2010 14:52:27)  [27]

Так, теперь переделывай обратно и больше так не делай


Sergey13   (2010-04-02 14:54:00) [8]

> [27] Валигози2   (02.04.10 14:52)
> Дело в том, что я их вообще не использую.

Дело в том, что ты их видимо используешь, хотя может и не догадываешься об этом. Но незнание закона, как известно, не освобождает от ответственности.


Валигози2   (2010-04-02 14:52:00) [9]


> Sergey13 ©   (02.04.10 14:24) [26]
> > [25] Валигози2   (02.04.10 13:15)
> > что типа чтото не все транзакции подтверждены
>
> Что ж ты их не подтвердил?

Дело в том, что я их вообще не использую. В тех двух местах, где использовал - переделал без транзакций сразу как заметил этот глюк, но дело оказалось не в этом...


Sergey13   (2010-04-02 14:24:00) [10]

> [25] Валигози2   (02.04.10 13:15)
> что типа чтото не все транзакции подтверждены

Что ж ты их не подтвердил?


Валигози2   (2010-04-02 13:15:00) [11]


> Sergey13 ©   (02.04.10 10:45) [23]
> > [22] Валигози2   (02.04.10 10:31)
>
> > Во-первых заказчик хочет видеть всё и сразу :)
> Он может хотеть увидеть даже прекрасных гурий в райских
> кущщах, но это никак не связано с проектированием приложения.
>  
> Это как в строительстве - есть отделка фасада и есть фундамент.

В идеале, сначала лучше построить макет, а то после фундамента может не подойти тот фасад как его видит заказчик...


> > Обещал заказчику "неразглашение" :) И так уже много чего
> выболтал... :)))
> Детский садик "Ромашка", старшая группа. Там тоже после
> просмотра Смешариков в секретики играют.
> Впрочем мне пофиг - это ты пишешь эту прогу.

Я знаю ;)


> Anatoly Podgoretsky ©   (02.04.10 11:15) [24]
> > Валигози2  (02.04.2010 10:31:22)  [22]
>
> > Обещал заказчику "неразглашение" :) И так уже много чего
> выболтал... :)))
>
> Теперь тебя посадят и расстреляют.

Надеюсь, что заказчик не читает форумы по программировнию :)))
Кстати, заметил, что AbsoluteDB в режиме MultiUser иногда при закритии приложения выдаёт какую-то ошибку о том, что типа чтото не все транзакции подтверждены и если после этого заглянуть в базу, то не всё изменения применяются... Впрочем, для моей задачи MultiUser не требуется, а в режиме SingleUser AbsoluteDB пока работает без замечаний...


Anatoly Podgoretsky   (2010-04-02 11:15:00) [12]

> Валигози2  (02.04.2010 10:31:22)  [22]

> Обещал заказчику "неразглашение" :) И так уже много чего выболтал... :)))

Теперь тебя посадят и расстреляют.


Sergey13   (2010-04-02 10:45:00) [13]

> [22] Валигози2   (02.04.10 10:31)

> Во-первых заказчик хочет видеть всё и сразу :)
Он может хотеть увидеть даже прекрасных гурий в райских кущщах, но это никак не связано с проектированием приложения.
Это как в строительстве - есть отделка фасада и есть фундамент.

> Обещал заказчику "неразглашение" :) И так уже много чего выболтал... :)))
Детский садик "Ромашка", старшая группа. Там тоже после просмотра Смешариков в секретики играют.
Впрочем мне пофиг - это ты пишешь эту прогу.


Валигози2   (2010-04-02 10:31:00) [14]


> Sergey13 ©   (02.04.10 09:48) [21]
> > [17] Валигози ©   (01.04.10 20:29)
> > а потом каким либо образом (наверно флэшками) эти данные
>
> > должны вливаться в основную базу.
>
> И есди записи от разных набивателей совпадают, то.....?

Они не могут совпасть, так как каждаязапись снабжается кроме порядкового id, также и уникальным кодом оператора. А вот с тем, что оператор мог в своей базе добавить инфу производителя, который уже прописан в базе пусть разгребается заказчик (что заказывал, то и получил :)). Заказчику же предоставляется возможность деактивировать любую запись и даже одним нажатием деактивировать все записи определённого оператора.
Впрочем, заказчик попросил, чтобы инфу о производителях мог добавлять только строго один он (хотя я и добавил в администраторском управлении возможность администратору разрешать/запрещать эту возможность любому оператору)


> > Так что мне ещё предстоит придумать как это лучшим образом
> реализовать.
> Я бы на твоем месте занялся С САМОГО НАЧАЛА этим вопросом.
>  Навешивание рюшечек это крайний с конца этап проектирования
> приложения.

Во-первых заказчик хочет видеть всё и сразу :)
Во-вторых я ещё сам не представляю как будет выгледеть окончательный вариант, поэтому я в проге набросал множество бутафории, чтобы заказчик ткнул в чтото что нужно переделать, прежде чем я к этой бутафории напишу рабочий код...


> > Теоретически он единственный
> ИМХО тебе в постановке задачи не хвататет практичности.
> Все теоретические изыски заказчика ты все равно не удовлетворишь.

Все - конечно нет, об этом даже не может быть и речи :) Но хотелось бы по-максимуму...


> Что это должно быть в оригинале то? Про что программа.

Обещал заказчику "неразглашение" :) И так уже много чего выболтал... :)))


> > [19] MsGuns ©   (01.04.10 23:46)
> > По кнопке "сохранить" таблица БД полностью очищается
>
> А так же все завязаные на нее дочки во всех коленах? Забавно.

То-то и оно...


Sergey13   (2010-04-02 09:48:00) [15]

> [17] Валигози ©   (01.04.10 20:29)
> а потом каким либо образом (наверно флэшками) эти данные
> должны вливаться в основную базу.

И есди записи от разных набивателей совпадают, то.....?

> Так что мне ещё предстоит придумать как это лучшим образом реализовать.
Я бы на твоем месте занялся С САМОГО НАЧАЛА этим вопросом. Навешивание рюшечек это крайний с конца этап проектирования приложения.

> Теоретически он единственный
ИМХО тебе в постановке задачи не хвататет практичности. Все теоретические изыски заказчика ты все равно не удовлетворишь.
Что это должно быть в оригинале то? Про что программа.

> [19] MsGuns ©   (01.04.10 23:46)
> По кнопке "сохранить" таблица БД полностью очищается

А так же все завязаные на нее дочки во всех коленах? Забавно.


Валигози2   (2010-04-02 09:43:00) [16]


> Jeer ©   (01.04.10 21:23) [18]
>
> > Способ задания порядка записей [D6, AbsoluteDB]
>
> Не использовать DBAware.
> Отдельные два поля: int в которых хранятся ссылки на левую
> и правую ближайшие записи. Т.е. организуем линейный связанный
> список.
> Построение "ручками", например, в StringGrid.

Первоначально я и хотел сделать без использования компонентов DBAware (в таком случае я бы и не написал этот вопрос в форуме) и если эта функция окажется очень важной для заказчика и он будет заострять на ней внимание, то прийдётся таки переделать. Просто хотелось сделать попроще, а насчёт двусвязного списка, то для данных в памяти это хорошее решения, но для баз данных помоему это лишнее усложнение...


> MsGuns ©   (01.04.10 23:46) [19]
> Реализация "перетаскивания" судя по всему по кнопке. Просто
> супер !
> Если я захочу единственную запись с 1000-й позиции перетащить
> на первую, кликнув 999 раз, то база "содрогнется"  999 раз
> !!!

:) Именно так. Пусть заказчик пощёлкает, может откажется от такой идеи... :)
А если серьёзно, то это основной способ. Однако если заказчику приспичит, можно и другие способы перемещения добавить. Например, в моём варианте можно добавить способ когда при нажатии одной кнопки текущая запись запоминается, потом перематываешь куда нужно нажимаешь другую кнопку и та запись перемещается на новое место. Наверно можно придумать и если нужно переместить не одну запись а несколько одновремменно, однако как я уже писал, в таком случае лучше уже делать не с помоью DBAware компонентов..


> Если так уж приспичило все же "перетаскивать", то реализовывать
> нужно так:
>
> ВСЯ таблица тянется на клиент и запоминается там (например
> через TClientDataSet или даже обычный стрингрид).
> Далее пользователь тягает что угодно и куда угодно - перемещение
> записи вверх или вниз реализуется примитивно посредством
> обмена данными между записью  - источником и записью - приемником.
>  При этом все операции с НД выполняются строго на клиенте.
>  Безо всякой  базы !!!

В моём случае нет смысла гонять таблицу туда-сюда по TClientDataSet, так как программа работает без сети (и сеть не предполагается), программа открывает базу в эксклюзивном режиме, все накопленные данные с разных машин собираются на основной флешками или RW-дисками (какому оператору что удобнее)


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

В таком случае никакой пользы от этой таблицы нет, так как это таблица производителей, и на неё по-любому будет ссылаться продукция (информацио о которой набирают операторы вообще отрезанные от сети). А в варианте, когда не перезаписыватся таблица полностью - такой проблемы нет.


MsGuns   (2010-04-01 23:46:00) [17]

Реализация "перетаскивания" судя по всему по кнопке. Просто супер !
Если я захочу единственнуюзапись с 1000-й позиции перетащить на первую, кликнув 999 раз, то база "содрогнется"  999 раз !!!

Если так уж приспичило все же "перетаскивать", то реализовывать нужно так:

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

По кнопке "сохранить" таблица БД полностью очищается,  НД сканируется и каждая запись добавляется  в таблицу с ее новым номером порядковым.

Все будет замечательно работать, НО !
Следует сразу забыть о многопользовательском доступе к БД. Ибо нормального решения для совместного использования таблицы, изменяемой таким трахнутым способом, просто не существует.
И еще. Нельзя (по крайней мере потенциально страшно граблиабельно) нигде в БД использовать ссылки на эту таблицу.


Jeer   (2010-04-01 21:23:00) [18]


> Способ задания порядка записей [D6, AbsoluteDB]


Не использовать DBAware.
Отдельные два поля: int в которых хранятся ссылки на левую и правую ближайшие записи. Т.е. организуем линейный связанный список.
Построение "ручками", например, в StringGrid.


Валигози   (2010-04-01 20:29:00) [19]


> Sergey13 ©   (01.04.10 10:16) [14]
> > [3] Валигози2   (31.03.10 16:56)> Забыл уточнить, что
> база "single user"Т.е. он это чисто для себя делает? Что
> бы не забыть поздравить с днем рожденья богатого партнера?
> Тогда я бы перестал оперировать такими масштабами, как "допустим
> поьзователь добавил 1000". ИМХО он эту тысячу будет несколько
> лет заводить, если это действительно "таблица производителей
> продукции".

Теоретически он единственный который имеет права добавлять/редактировать данные о производителях (но не обязательно). А информацию о продуктах этих производителей будет набирать множество людей. Причём главное условие, чтобы всё работало без сети. Каждый набивает данные на своей машине, а потом каким либо образом (наверно флэшками) эти данные должны вливаться в основную базу. Так что мне ещё предстоит придумать как это лучшим образом реализовать. В идеальном случае можно будет даже из основной базы удалять (или ещё может чтото делать) все записи определённого оператора (т.е. каждая запись ещё должна "помнить" кто её набрал)... Ну это уже другая история...

А по поводу вопроса из этого топика - я сделал так:
Дополнительное поле (я его назвал "Slot") типа Int32. Записи в этом поле нумеруются от 1 до N (где N - количество всего записей в таблице).
Когда добавляется новая запись - на событии AfterInsert тут же присваивается значение поля "Slot":

procedure TDM.qu_BrandsAfterInsert(DataSet: TDataSet);
begin
 qu_BrandsSlot.AsInteger:=qu_Brands.RecordCount+1;
 BrandsInput_Form:=TBrandsInput_Form.Create(nil);
 try
   if BrandsInput_Form.ShowModal=mrOk then DataSet.Post else DataSet.Cancel;
 finally
   BrandsInput_Form.Free;
 end;
end;


Когда пользователь нажимает кнопку вверх (чтобы переместить запись выше) происходит следующее:

procedure TMain3Form.btBrands_upClick(Sender: TObject);
var
 CurId, CurSlot: Integer;
begin
 if not DM.qu_Brands.Active or DM.qu_Brands.IsEmpty then Exit;

 CurId:=DM.qu_Brandsid.AsInteger;
 CurSlot:=DM.qu_BrandsSlot.AsInteger;

 if CurSlot=1 then Exit;

 DM.qu_trans.Close;
 DM.qu_trans.SQL.Text:=
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot)+' WHERE Slot='+IntToStr(CurSlot-1)+';'+
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot-1)+' WHERE id='+IntToStr(CurId)+';';
 DM.qu_trans.ExecSQL;

{
 DM.qu_trans.Close;
 DM.qu_trans.SQL.Text:=
   'START TRANSACTION;'+
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot)+' WHERE Slot='+IntToStr(CurSlot-1)+';'+
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot-1)+' WHERE id='+IntToStr(CurId)+';'+
   'COMMIT;';
 try
   DM.qu_trans.ExecSQL;
 except
   DM.qu_trans.SQL.Text:='ROLLBACK';
   DM.qu_trans.ExecSQL;
   raise;
 end;
}

 DM.qu_Brands.Refresh;
end;


А по нажатию кнопки вниз наоборот:

procedure TMain3Form.btBrands_downClick(Sender: TObject);
var
 CurId, CurSlot: Integer;
begin
 if not DM.qu_Brands.Active or DM.qu_Brands.IsEmpty then Exit;

 CurId:=DM.qu_Brandsid.AsInteger;
 CurSlot:=DM.qu_BrandsSlot.AsInteger;

 if CurSlot=DM.qu_Brands.RecordCount then Exit;

 DM.qu_trans.Close;
 DM.qu_trans.SQL.Text:=
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot)+' WHERE Slot='+IntToStr(CurSlot+1)+';'+
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot+1)+' WHERE id='+IntToStr(CurId)+';';
 DM.qu_trans.ExecSQL;

{
 DM.qu_trans.Close;
 DM.qu_trans.SQL.Text:=
   'START TRANSACTION;'+
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot)+' WHERE Slot='+IntToStr(CurSlot+1)+';'+
   'UPDATE tbBrands SET Slot='+IntToStr(CurSlot+1)+' WHERE id='+IntToStr(CurId)+';'+
   'COMMIT;';
 try
   DM.qu_trans.ExecSQL;
 except
   DM.qu_trans.SQL.Text:='ROLLBACK';
   DM.qu_trans.ExecSQL;
   raise;
 end;
}

 DM.qu_Brands.Refresh;
end;


Единственная загвоздка у меня была с удалением записи. Я её решил так:

procedure TDM.qu_BrandsBeforeDelete(DataSet: TDataSet);
begin
 FDeleted_BrandsSlot:=qu_BrandsSlot.AsInteger;
end;

procedure TDM.qu_BrandsAfterDelete(DataSet: TDataSet);
begin
 qu_trans.SQL.Text:='UPDATE tbBrands SET Slot=(Slot-1) WHERE Slot>'+IntToStr(FDeleted_BrandsSlot);
 qu_trans.ExecSQL;
end;


YurikGL   (2010-04-01 20:27:00) [20]

Делается собственное поле типа sortorder, которое динамически вычисляется...


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо