Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.06.20;
Скачать: CL | DM;

Вниз

Исключение записи из выборки   Найти похожие ветки 

 
Rouse_ ©   (2004-05-25 14:03) [0]

Ситуация:
при помощи ADOQuery делаю выборку записей и модифицирую их по определенному алгоритму...
Но иногда бывает что в выборку попадают записи которые в данный момент мне не нужны.
В качестве примера:
производим поиск всех записей начинающихся с букв "ул"
в результате имеем кучу записей выглядящих как:
"улица Каширская"
"ул. Пролетарская"
но среди них затесывается иногда и такое:
"Ульяновск"
"Улан-Удэ"
(данные привел просто как пример)

Теперь вопрос:
Можно ли как нибудь исключить записи мне не подходящие в данный момент из общей выборки?
Свойства Remove я к сожалению не нашел...

Почему не подходит модификация запроса в виде WHERE?
Потому что сам запрос выполняется в течении нескольких секунд и с каждой удаленной таким макаром записью ждать заново еще несколько секунд некрасиво...

Почему не подходит фильтр?
Фильтр может быть и подходит, но в дальнейшем я передаю всю выборку в таблицу таким способом:
ADOTable.RecordSet := ADOQuery.RecordSet;
и продолжаю работать уже через таблицу...
По всей видимости придется плодить строку фильтра с каждым удалением.

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


 
Sandman25+1   (2004-05-25 14:08) [1]

Не уверен, что правильно понял, но все же попробую.
Если нельзя написать update и очень хочется работать именно с While not Eof do ... Next, то я бы в этот цикл добавил вызов функции, возвращающей значение True только для тех записей, которые нужно изменять.


 
Vlad ©   (2004-05-25 14:11) [2]


> Sandman25+1   (25.05.04 14:08) [1]


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

Ну это фактически тоже что и DataSet.OnFilterRecord


 
Sandman25+1   (2004-05-25 14:16) [3]

[2] Vlad ©   (25.05.04 14:11)

OnFilterRecord может использоваться другими свойствами/методами TDataSet, в том числе и RecordSet, а пользовательская функция заведомо никем не используется. Хотя, возможно, действительно нет никакой разницы.


 
Rouse_ ©   (2004-05-25 14:19) [4]

Нет, понял ты конечно правильно но немного не так :)
см > [2] Vlad ©   (25.05.04 14:11) :)

А нужно именно исключение вручную из уже сделанной выборки определенных записей...

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


 
Sandman25+1   (2004-05-25 14:25) [5]

[4] Rouse_ ©   (25.05.04 14:19)

Так это пользовательский выбор? Можно сделать новый TClientDataSet, перекачать в него данные, а потом пользователь бы удалял все, что он хочет.
Либо как альтернатива, использовать CashedUpdates=true. Только не уверен, что это подойдет для AdoQuery.


 
Vlad ©   (2004-05-25 14:26) [6]


> Rouse_ ©   (25.05.04 14:19) [4]

Используй TClientDataSet или TADODataSet (по-моему там тоже можно отвязать данные от базы), и удаляй из клиентского набора данных, но при этом не отражай в базе.


 
DenK_vrtz ©   (2004-05-25 14:28) [7]

как вариант
DBGrid1 c включенной dgMultiSelect
А потом цикл по DataSet c проверкой выделения строки и update


 
Vlad ©   (2004-05-25 14:40) [8]

Впринципе вопрос, как я понял сводится к следующему:
нужно удалить данные из DataSet, но не удалять физически из таблицы. Так ?
Тут еще как вариант, можно было бы использовать транзакции. То есть открываешь транзакцию, удаляешь записи из ADOQuery, затем делаешь с Recordset все необходимые действия, и в конце - откат транзакции.
Но если речь идет о Access, например, то не уверен что там вобще существует понятие транзакций. В этом случае попробуй вариант с клиентским набором данных ([6])


 
Rouse_ ©   (2004-05-25 15:19) [9]

Да, сейчас попробую через ClientDataSet
Фильтр по некоторой причине не подошел...


 
Rouse_ ©   (2004-05-25 23:12) [10]

Все же сделал на фильтрах - при более глубоком разборе они оказались самым оптимальным вариантом...

Жаль конечно, я думал что sniknik&Polevi - подскажут вариант решения проблемы, но после разбора кода самих компонентов оказалось что решения именно так, как я себе представлял (Remove определенной записи в наборе) не существует... Хотя я просто мог его не найти или не обратитть на него внимания... (что маловероятно)
Мне думается если мои доводы верны - то это большое упущение со стороны Борланда (а именно модификация уже полученной выборки без дополнительных ухищрений)
Но это так... мое ИМХО.

Всем спасибо.


 
sniknik ©   (2004-05-25 23:59) [11]

> модификация уже полученной выборки без дополнительных ухищрений
на клиенте легко.
...
ADODataSet.Open;
ADODataSet.Connection:= nil;
ADODataSet.Delete; <- базу не затронет
либо ставиш ltBatchOptimistic и тоже удаляй как хочеш только UpdateBatch не делай, тогда тоже ничего в базе не изменится.

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


 
Sandman25+1   (2004-05-26 09:03) [12]

[11] sniknik ©   (25.05.04 23:59)

>но ты вроде в запросе хотел, там только один способ модифицировать выборку после командой SQL, HAVING но тебе не подойдет

Что Вы имеете в виду? Having - точно такая же часть select, как и where или from.


 
sniknik ©   (2004-05-26 10:28) [13]

> Что Вы имеете в виду?
SELECT * FROM Table1 HAVING ID = 0
-> EOleException : Предложение HAVING (ID=0) без группировки

SELECT ID, First(Name) FROM Table1 GROUP BY ID HAVING ID = 0
-> ok

какой запрос в вопросе? я лично его вообще не вижу.


 
Polevi ©   (2004-05-26 10:32) [14]

>Rouse_ ©   (25.05.04 23:12) [10]
тебе нужен отсоединенный датасет

tempDataset:=TADODataset.Create(nil);
try
 tempDataset.RecordSet=ADOQuery1.Recordset;
 while not tempDataset.Eof do
 begin
   if condition then
     tempDataset.Delete;
   tempDataset.Next;
 end;
finally
 tempDataset.Free;
end;

ADOTable1.RecordSet=tempDataset.Recordset;


 
Polevi ©   (2004-05-26 10:33) [15]

PS
сорри, tempDataset.Free в конце еснно :)


 
Rouse_ ©   (2004-05-26 10:37) [16]

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

А запрос у меня простой

SELECT * FROM MainTable WHERE StreetName LIKE "ул%"

где
MainTable - имя таблицы
StreetName - имя колонки


 
Sandman25+1   (2004-05-26 10:50) [17]

[13] sniknik ©   (26.05.04 10:28)

Все равно select остается select"ом, с having он или без.


 
sniknik ©   (2004-05-26 10:54) [18]

> Потому что сам запрос выполняется в течении нескольких секунд и с каждой удаленной таким макаром записью ждать заново еще несколько секунд некрасиво...
> SELECT * FROM MainTable WHERE StreetName LIKE "ул%"
запрос в таком виде использует индекс (если он есть), и не будет менее "напряжным"  чем такой например

SELECT * FROM MainTable WHERE StreetName LIKE "улица%" or StreetName LIKE "ул.%"
ждать больше не придется.
или
SELECT * FROM MainTable WHERE StreetName LIKE "ул[и.]%"
(хотя в этом случае в использовании тндекса не уверен, по идее должен использоватся)


 
sniknik ©   (2004-05-26 10:58) [19]

Sandman25+1   (26.05.04 10:50) [17]
а где я чтонибудь против говорил? > [11]?  попытайся не только прочитать но и понять (возможно не совсем верно расставлены запятые, но смысл фразы по моему понятен)


 
Sandman25+1   (2004-05-26 11:05) [20]

[19] sniknik ©   (26.05.04 10:58)

Видимо, я уже не пойму. Извините, если что.


 
Rouse_ ©   (2004-05-26 11:48) [21]

> [14] Polevi ©   (26.05.04 10:32)
В таком варианте происходит удаление записи из физической таблицы...

вот как я решил данную проблему:

procedure TfrmRestructuringTable.mnuRemoveRecClick(Sender: TObject);

 function CopyRecordSet(RecordSet: _RecordSet): _RecordSet;
 var
   adoStream: OleVariant;
 begin
   adoStream := CreateOLEObject("ADODB.Stream");
   try
     Variant(RecordSet).Save(adoStream, adPersistADTG);
     Result := CreateOLEObject("ADODB.RecordSet") as _RecordSet;
     Result.CursorLocation := adUseClient;
     Result.Open(adoStream, EmptyParam, adOpenStatic, adLockOptimistic,
       adOptionUnspecified);
   finally
     adoStream := UnAssigned;
   end;
 end;

var
 TempDataset: TADODataSet;
begin

 TempDataset := TADODataSet.Create(nil);
 try
   TempDataset.Recordset := CopyRecordSet(SourceQuery.Recordset);
   TempDataset.Delete;
   SourceQuery.Recordset := TempDataset.Recordset;
 finally
   TempDataset.Free;
 end;
end;


Всем спасибо за помощь...


 
Rouse_ ©   (2004-05-26 12:15) [22]

точнее даже вот так лучше переписать:

var
 TempDataset: TADODataSet;
 Mark: TBookmark;
begin
 TempDataset := TADODataSet.Create(nil);
 try
   TempDataset.Recordset := CopyRecordSet(SourceQuery.Recordset);
   TempDataset.MoveBy(SourceQuery.RecNo - 1);
   TempDataset.Delete;
   Mark := TempDataset.GetBookmark;
   try
     SourceQuery.Recordset := TempDataset.Recordset;
   finally
     SourceQuery.GotoBookmark(Mark);
     TempDataset.FreeBookmark(Mark);
   end;
 finally
   TempDataset.Free;
 end;
end;


 
sniknik ©   (2004-05-26 12:16) [23]

> Rouse_ ©   (26.05.04 11:48) [21]
сложно...
гораздо сложнее чем предлагал > ADODataSet.Connection:= nil;
и уж явно копирование всей выборки идет дольше чем простое уточнение условия в WHERE (если считать разницу времени от неточного к точному, именно ее ты добавляеш).


 
Rouse_ ©   (2004-05-26 14:13) [24]

> [23] sniknik ©   (26.05.04 12:16)
Дело в том что после удаления ненужных записей у меня останется набор записей важными из которых являются два поля
первое поле ID второе строка типа Улица, дом, корпус, квартира
и мне эти строки необходимо разбить и перетащить каждое значение в другие поля в этой же таблице, а если я удалю запись при отключенной таблице и потом подключусь - то запись то там исчезнет (я так думаю)
короче на данный момент этот вариант полностью устраивает... :)



Страницы: 1 вся ветка

Текущий архив: 2004.06.20;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.028 c
3-1085827922
Denis_Visma
2004-05-29 14:52
2004.06.20
Вопрос по нескольким ДатаСеиам и одной транзакции


1-1086761992
artem_123
2004-06-09 10:19
2004.06.20
вопрос по mainmenu


4-1084362767
cdsvalik
2004-05-12 15:52
2004.06.20
Как редактировать в Delphi exe файл?


9-1077298936
Ser_00
2004-02-20 20:42
2004.06.20
Ссылки.


1-1086378897
rrew
2004-06-04 23:54
2004.06.20
mytexteditor.exe textfile.txt