Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Зависание Locate


Автор: SergXPI 25.9.2007, 13:35
Привет всем.
Подскажите пожалуйста в чем проблема.
На этапе поиска данных в таблице с помощью Locate происходит зависание программы.
У меня есть подозрения, что проблема в самой таблице. 
Как проверить целая таблица(ее индексы) или нет?

Автор: ALeXandrK 25.9.2007, 16:06
Октрой таблицу, да и посмотри целые ли там индексы.
Если таблица откроется, значит все нормально.

Может у тебя база большая... база локальная или удаленная?

Автор: SergXPI 25.9.2007, 17:32
База локальная.

Зависание происходит где то на 1000 шаге цикла.

В цикле происходит 
 - добавление данных в таблицу
 - поиск (Locate) необходимых данных и удаление

Автор: ALeXandrK 25.9.2007, 19:21
Вообще в таком случае лучше все запросами SQL делать. 
Он и быстрее и качественнее сделает, а если засунишь процедуру в
Thread, то и пользователя заставлять ждать не придется smile 

Твой подход просто варварский.

Автор: SergXPI 25.9.2007, 21:29
Цитата(ALeXandrK @ 25.9.2007,  19:21)
Твой подход просто варварский.

Что именно? использование Locate?

Если таблица запорчено, то я не думаю что SQL запрос будет работать

Автор: ALeXandrK 25.9.2007, 23:25
Может я и зря так написал. Все зависи от того, что ты делаешь Locatом.
Обычно, если Locate есть в цикле, то его можно без проблем заменить
на запрос.

Если бы таблица была запорчена, она, вероятнее всего, и не открылась бы.

Приведи часть кода с циклом.

Автор: SergXPI 26.9.2007, 10:13
Код

 IF Not(Tabl_Post.Locate(Locate_Str,Locate_Array,[loCaseInsensitive]))
                Then Begin // не найден товар у поставщика
                          Tabl_Post.Append;
                         End
                Else Begin //товар найден
                         Tabl_Post.Edit;
                        End;  
 ....
 Tabl_Post.Post;                         


Фрагмент года (приход товара по накладным). 
В накладной может быть 1..10000 наименований.
Когда проводится одна накладная я работаю с  переиндексированной копией таблицы. 
Это конечно замедляет, но при этом есть всегда возможность сделать откат при возникновении ошибки.
Но существует также необходимость провести сразу порядка 200 накладных и тогда этот метод очень тормозит. 
А без переиндексации начинает виснуть и виснит на Locate
В таблице есть Autoinc поле может проблема в нем?

Проблема в том, что не возникает исключительная ситуация, а программа просто виснит?

Автор: ALeXandrK 26.9.2007, 19:21
Раз этот не работает я бы поступил бы так...
  • 1. Проверял существование такой записи с помощью LookUp - она быстрее Locate, т.к. курсор не двигает;
  • 2. Обновлял бы, если такая запись существует, запросом;
  • 3. Добалял бы запросом, если не существует;

Цитата

Проблема в том, что не возникает исключительная ситуация, а программа просто виснит?


Ну и правильно, ведь в коде ошибки нет, а вот сервер БД может дать сбой...
Может драйвер БД плохой. Поищи в инете более новую версию.

Автор: SergeBS 27.9.2007, 10:12
SergXPI, 
1. Использовать вместо линейного locate индексный seek религия не позволяет? Выигрыш тем больше, чем больше база.
2. Что мешает при поиске в отдельном потоке (например) выводить № записи в label (например) с периодом в 1-2 сек., дабы убедиться, что не висит, а ищет? Или строку поиска выводить?

Автор: Akella 27.9.2007, 10:29
мало того, на сколько мне известно, то locate неправльно работает со своими параметрами: loCaseInsensitive и loPartialKey

не раз с этим сталкивался

Автор: SergXPI 27.9.2007, 17:10
Цитата(SergeBS @ 27.9.2007,  10:12)
1. Использовать вместо линейного locate индексный seek религия не позволяет? 

Религия позволяет. Знания не позволяют.
У обекта TTable я такой функции не нашел.
SergBS, Если не сложно напиши пример.

Автор: Akella 28.9.2007, 10:51
клавиша F1 наверное выламана?

Цитата

Searches for a record using the current index.

Pascal
function Seek(const KeyValues: Variant; SeekOption: TSeekOption = soFirstEQ): Boolean;

примеры
SuccessVar := ADODataSet1.Seek('Jones', soFirstEQ);
ADODataSet1.Seek(VarArrayOf([90030, 90020]), soFirstEQ);

Seek Option  Meaning  
soFirstEQ   Record pointer positioned at the first matching record, if one is found, or at the end of the dataset if one is not found.   
soLastEQ   Record pointer positioned at the last matching record, if one is found, or at the end of the dataset if one is not found.   
soAfterEQ   Record pointer positioned at matching record, if found, or just after where that matching record would have been found.   
soAfter   Record pointer positioned just after where a matching record would have been found.   
soBeforeEQ   Record pointer positioned at matching record, if found, or just before where that matching record would have been found.   
soBefore   Record pointer positioned just before where a matching record would have been found.   


Using the Seek method depends on the settings of a few properties. IndexName must be set to activate the index to use, CommandType must be cmdTableDirect (for TADODataSet, set TableDirect to true for a TADOTable), CursorLocation must be clUseServer, and CursorType must be ctKeySet. 


Автор: SergeBS 28.9.2007, 12:56
SergXPI, 
Не могу: я BDE не применяю (и тебе не советую). Сразу не обратил внимания :(. Так что:
1. Попробуй найти легкий компонент вместо BDE. Скорее всего будет сам по себе работать быстрее.
2. Посмотри как насчет ADO-SQL.
Т.е. прочитай http://forum.vingrad.ru/topic-92925.html

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)