![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Удаление большого количества записей firebird 1.5 [D6, firebird]
Dim!S © (2009-10-28 08:43:00)Уважаемые форумчане!
Есть бд на Firebird 1.5 (gdb). Необходимо из неё удалить каждые несколько записей...
вот кусок кода, но иногда программа выдаёт сообщение out of memory
...
IBTable1.DisableControls;
cnt_Rec := 0;
IBTable1.First;
with IBTable1 do
while not(EOF) do
begin
IBTable1.First;
Delete;
Delete;
Delete;
Delete;
Next;
Inc(cnt_Rec);
Application.ProcessMessages;
if cnt_Rec >= 10000 then
begin
ShowMessage(IntToStr(RecNo) + ' - ' + IntToStr(cnt_Rec));
cnt_Rec := 0;
IBTransaction1.Commit;
IBTransaction1.StartTransaction;
end;
end;
IBTransaction1.Commit;
IBTable1.EnableControls;
Label2.Caption := TimeToStr(Time);
IBTable1.Refresh;
...
Как лучше написать код для указанной задачи? Записей в таблице может быть миллион. К базе никто не подключен... Может лучше через IBQuery ии есть более изящный способ?
P.S. с firebird дело не имел вообще, только с paradox
Большое спасибо.
Dim!S (2009-10-30 08:19:00) [21]в предыдушем посте: T1 заменить на TOrders
Dim!S (2009-10-30 08:18:00) [22]что непонятно?
удалить надо из таблицы T1 записи по определённому условию. НЕ каждую n-ю!
Есть несколько таблиц. В таблице T1 есть поля связанные со справочными по внешнему ключу.
Пример:
TOrders
ID
ShopID
ClientID
TShops
ID
Name
TClients
ID
FIO
Необходимо из TOrder удалить записи конкретного магазина и конкретного клиента. Как сделать это чере запрос не знаю.
sniknik (2009-10-30 08:01:00) [23]> Может надо переменную xx описать? Как это сделать?
поменял вопрос, но не поменял стиль... по статье, ты опять не говоришь "мне надо сделать X", а начинаешь с того, что "как делать Y?" которое уже следствие твоих умозаключений как делается X, а делать Y бессмысленно, описывать переменную xx глупо, по всем признакам она у тебя уже должна быть, и должна быть не переменной а полем таблицы T1, иначе весь запрос теряет смысл (а то что ты делаешь мы не видим, ты не сказал, мы видим только бессмысленный запрос который к тому же дает неизвестную (не показанную тобой) ошибку).
и что на это можно сказать "Как это сделать?" единственный остающийся рабочий вариант как это делается - приглашается ПРОГРАММИСТ, и говорится ему "напишите программу". вариант самому у ТЕБЯ не получится.
Dim!S (2009-10-30 07:55:00) [24]Пробую в IBExpert 4.5 (самая свежая с сайта)
Dim!S (2009-10-30 07:37:00) [25]Именение запроса
DELETE xx FROM T1
WHERE xx=(
select T1.F1
from T1, T2
where
(cast(T1.F2 as integer) between 50 and 90) AND
(T1.F3=T2.F1) AND
(T2.F3=100)
на
DELETE xx FROM T1
WHERE xx in (
select T1.F1
from T1, T2
where
(cast(T1.F2 as integer) between 50 and 90) AND
(T1.F3=T2.F1) AND
(T2.F3=100)
приводит к сообщению об ошибке Between. Может надо переменную xx описать? Как это сделать?
Спасибо.
RWolf (2009-10-30 01:33:00) [26]
> Что-то типа этого:
да, что-то вроде.
только WHERE xx IN (...) .
Сергей М. (2009-10-29 20:28:00) [27]
> Dim!S (29.10.09 17:19) [52]
Так это уже совсем другая грядка и совсем другие морковки)
Dim!S (2009-10-29 17:19:00) [28]Удаление через IBQuery работает на порядок быстрее IBTable... заинтересовался... :)
Простой запрос удаляет ненужные записи из таблицы, а вот как усложнить условие не знаю пока...
Что-то типа этого:
DELETE xx FROM T1
WHERE xx=(
select T1.F1
from T1, T2
where
(cast(T1.F2 as integer) between 50 and 90) AND
(T1.F3=T2.F1) AND
(T2.F3=100)
T1.F3 - внешний ключ на T2
T2.F1 - ключевое поле второй таблицы
или надо использовать хранимые процедуры? Но в БД я их интегрировать, скорее всего, не смогу (запаролена БД)...
Anatoly Podgoretsky (2009-10-29 11:33:00) [29]
> Меня разделывать? за что??? :)
Да не тебя.
Сергей М. (2009-10-29 11:26:00) [30]
> разве записи в таблице идут не в порядке в каком они добавлены
Нет, не идут.
И не обязаны идти.
Куда их сервер соизволит разместить - там они и будут жить.
RWolf (2009-10-29 11:17:00) [31]
> а разве записи в таблице идут не в порядке в каком они добавлены
> (без испоьзования сортировки, естественно)?
нет, никаких предположений о порядке хранения записей делать нельзя.
Dim!S (2009-10-29 10:50:00) [32]Меня разделывать? за что??? :)
"Не нужно обращаться к записям таблицы по их порядковому номеру" - я и не пытаюсь обращаться к записям по их порядковому номеру...
"это по произвольному непредсказуемомм набору" - а разве записи в таблице идут не в порядке в каком они добавлены (без испоьзования сортировки, естественно)?
Ок, путь понятен, осталось снарядиться и можно двигаться по нему...
Всем большое спасибо.
Anatoly Podgoretsky (2009-10-29 10:33:00) [33]
> На 12(!) посте была попытка намекнуть на то, что пора бы
> уже открыть для себя SQL-оператор DELETE, но все присутствующие
> ее упорно игнорируют и продолжают рассматривать варианты
> с шести и семиугольными колесами...
Вот и выдай код, который будет удалять по четыре записи подряд и оставлять пятую и это по произвольному непредсказуемомм набору, вот как захочет сервер, так и сделать.
Возможно мы его под хвост и гриву разделаем (вместе с автором) как непригодный.
Dim!S (2009-10-29 10:11:00) [34]"если таковой нет (т.е. достигнут конец НД), взводит флаг EOF" вот про это не знал... :(
Чем твое "прореживание" лучше оно не лучше, оно ДРУГОЕ, а если необходимо чтобы записи остались и до начала текущего квартала?
Порядок записей по ID (автоинкремент).
P.S. прореживать будем по условию (придумаем чего-нибудь), но вариант с удалением каждой кроме N записи интересен гипотетически...
RWolf (2009-10-29 10:04:00) [35]
> И всё же (ради любопытства) как удалить кждую n-ю запись
> с помощью IBQuery?
Не нужно обращаться к записям таблицы по их порядковому номеру, для реляционных БД это идеологически неверно. Заведи ключевое поле, заполненное уникальными значениями, и делай выборки/изменения/удаления по нужному значению.
Sergey13 (2009-10-29 09:01:00) [36]> [42] Dim!S (29.10.09 06:23)
> И всё же (ради любопытства) как удалить кждую n-ю запись с помощью IBQuery?
Так
> [34] PEAKTOP © (29.10.09 03:40)
даже код тебе дал. Тебе надо обдумать и модифицировать только фразу WHERE (TB1.FIELD = ...) AND (TB1.FIELD2 = ...). Но для того что бы это сделать надо понять что тебе надо. А ты это упорно скрываешь, как партизан. Чем твое "прореживание" лучше чем например "удалить все данные с датой, меньшей чем начало текущего квартала" например? Как обеспечивается порядок записей в твоей ТТабле?
Сергей М. (2009-10-29 08:15:00) [37]
> Dim!S (29.10.09 03:02) [33]
Я надеюсь, ты в курсе, что метод Delete после успешного удаления тек.записи автоматически двигает курсор к следующей существующей записи и, если таковой нет (т.е. достигнут конец НД), взводит флаг EOF ?
Dim!S (2009-10-29 06:23:00) [38]Спасибо, в принципе понятно...
Думаю при возникновении задачи с использованием сети буду копать только в сторону query...
И всё же (ради любопытства) как удалить кждую n-ю запись с помощью IBQuery?
Inovet (2009-10-29 06:00:00) [39]> [39] Dim!S (29.10.09 05:05)
> Есть ли задачи где query не эффективен или мало эффективен
> по сравнению с table?
внутри TIBTable в отличии от для Парадокса TTable всё равно вся работа ведётся через SQL запросы, есть TIBDataSet.
PEAKTOP (2009-10-29 05:57:00) [40]> Есть ли задачи где query не эффективен или мало эффективен
> по сравнению с table?
>
> P.S. программирование не является приоритетным направлением,
> есть несколько разработанных локальных БД на paradox...
> по большей части для души...
В том то и проблема, что в голове Paradox. Paradox является файловой БД, в которой единицей хранения информации является файл таблицы. Оттого и такая философия работы. TTable открывает доступ к файлу через BDE-API, оттого он (компонент) такой быстрый.
Firebird является потомком (1.5) и внуком (> 2.0) InterBase и философия работы с ним совершенно другая. На сервер передаются запросы (команды SELECT) и команды (INSERT/UPDATE/DELETE), а сервер сам уже управляет данными. Т.е. ни одна из API-функций сервера не имеет доступа к данным, они лишь передают команды серверу, а сервер сам управляет физически файлом базы данных. Поэтому базовым компонентом для работы с базами данных Firebird является TIBSQL, т.е. - "простая команда".
Далее - есть класс TIBCustomDataSet, который инкапсулирует пять классов TIBSQL для формирования набора данных, привычного для философии Delphi. Почему именно пять ?
SelectSQL - для команды SELECT, которая возвращает набор данных.
RefreshSQL - почти идентична команде SelectSQL, необходима для того, чтобы перезагрузить с сервера текущуюзапись набора данных, если она была изменена.
InsertSQL/UpdateSQL/DeleteSQL - для того, чтобы управлять изменениями в наборе данных.
От класса TIBCustomDataSet порождены классы TIBDataSet, TIBTable, TIBQuery, TIBStoredProc. Наиболее полный доступ к возможностям класса TIBCustomDataSet открывает класс TIBDataSet, позволяя управлять всеми пятью командами SQL. Класс TIBQuery - поскромнее, он позволяет управлять только командой SelectSQL. Класс TIBTable вообще маскирует работы команд SQL, эти команды просто автоматически формируются "внутри" класса таким образом, что у тебя возникает иллюзия будто бы компонент действительно физически работает с таблицей. Нет никакой таблицы. ("Нет никакой ложки..." бу-го-га!) Есть пять команд SQL, которые трудятся в фоне и создают для тебя иллюзию.
Для чего его тогда придумали ? Чтобы программистам в далеком 1999 году с появлением Delphi 5 было легче сломать старые стереотипы программирования, чтобы было перевести свои старые приложения с BDE-архитектуры на архитектуру компонентов IBX (и убедиться, что старая философия программирования, основанная на TTable, в IBX никуда не годится).
Поэтому сравнивать производительность двух классов потомков от одного класса предка - не совсем корректно, т.к. можно привести примеры "в любую сторону", в зависимости от желаемого результата и кривизны рук.