Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.06.20;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.032 c
1-1086416398
FragMan
2004-06-05 10:19
2004.06.20
Руссификация dll


6-1082858101
FatBase
2004-04-25 05:55
2004.06.20
Отправка почты: как всё объединить?


1-1086450716
parovoZZ
2004-06-05 19:51
2004.06.20
Окно как в проводнике


1-1086255747
kukuikar
2004-06-03 13:42
2004.06.20
Корректировка вопроса о шифровании


6-1083057490
Veon
2004-04-27 13:18
2004.06.20
Подсчёт трафика





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский