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

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

Удаление большого количества записей firebird 1.5 [D6, firebird]


Страницы:   1 2 3 4

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 никуда не годится).

Поэтому сравнивать производительность двух классов потомков от одного класса предка - не совсем корректно, т.к. можно привести примеры "в любую сторону", в зависимости от желаемого результата и кривизны рук.


Страницы:   1 2 3 4

Наверх

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