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

Вниз

Удаление большого количества записей firebird 1.5   Найти похожие ветки 

 
Dim!S   (2009-10-28 08:43) [0]

Уважаемые форумчане!

Есть бд на 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

Большое спасибо.


 
sniknik ©   (2009-10-28 09:02) [1]

> Может лучше через IBQuery
неважно через что... главное запросом. (а то ты счас поменяешь компонент с IBTable1 на IBQuery а код оставиш неизменным...)


 
Sergey13 ©   (2009-10-28 09:31) [2]

Честно говоря, чуднее алгоритма удаления из таблицы я не встречал. Типа оставить только каждую пятую запись? Похоже на прореживание моркови на грядке.
А смысл этого действа, если не сложно, можешь рассказать?


 
Сергей М. ©   (2009-10-28 09:54) [3]


> Записей в таблице может быть миллион


А может быть и не миллион, а, скажем, всего дюжина.
И тогда грабли хлобыстнут еще больней, чем по out of memory


 
Dim!S   (2009-10-28 10:55) [4]

>Sergey13 а в чём чудность? Ну если так нао, именно каждые 4 или 5 или 6 записей оставляя следующую. Не спрашивайте зачем ;)

>Сергей М. грабли на таблице в 50 МБ (150 тыс) не бьют :) а вот больше засада...

>All Форумчане! Дайте, пожалуйста, намётки на реализацию этой задачи...Я предполагаю так:

начинаем транзакцию
удаляем (допустим 50 тыс. записей)
заканчиваем транзакцию

и это в цикле от первой записи до последней
С реализацией туговато, ввиду отсутствия практического опыта работы с FireBird...

Спасибо.


 
Сергей М. ©   (2009-10-28 11:00) [5]


> С реализацией туговато, ввиду отсутствия практического опыта
> работы с FireBird


Те же самые грабли хряснут по тому же самому месту и в Парадоксе.
СУБД здесь ни причем.


> грабли на таблице в 50 МБ (150 тыс) не бьют


Понатыкай в тело цикла вместо четырех 150 тыс. вызовов метода delete - лупанут всенепременно)


 
sniknik ©   (2009-10-28 11:00) [6]

> Не спрашивайте зачем ;)
> Я предполагаю так:
http://delphimaster.net/view/2-1256632484/
в [28] там ссылка на хорошую статью. мне понравилась. и ведь именно так все и есть...


 
Sergey13 ©   (2009-10-28 11:13) [7]

> [6] sniknik ©   (28.10.09 11:00)
> http://delphimaster.net/view/2-1256632484/
> в [28] там ссылка на хорошую статью.

Шикарно! 8-)

> [4] Dim!S   (28.10.09 10:55)
> Не спрашивайте зачем ;)

Прочитай обязательно статейку!
Ты же просишь "изящный способ", но скрываешь условия. И где логика?


 
Dim!S   (2009-10-28 11:13) [8]

Спасибо за ссылку, гляну...

И всё же, как можно проредить базу данных?
Или лучше создать новую и в неё каждую n-ю запись добавлять?


 
Sergey13 ©   (2009-10-28 11:21) [9]

> [8] Dim!S   (28.10.09 11:13)

Ты сначала глянь, а потом сформулируй вопрос. 8-)


 
Сергей М. ©   (2009-10-28 11:23) [10]


> как можно проредить базу данных?


Значит все-таки морковка)

Ну ты сам посуди - флаг EOF ты проверяешь всего один раз перед каждой итерацией цикла. А в теле цикла ты беспардонно пытаешься удалить столько записей, сколько тебе захотелось, нисколько не задумываясь о том, что при очередном delete или next этот флаг может принять значение True !


 
Dim!S   (2009-10-28 15:12) [11]

"флаг EOF ты проверяешь всего один раз перед каждой итерацией цикла" -
ну конечно же!!! Большое спасибо....

И всё-таки морковка... :)
Форумчане, подскажите кусочек кода по оптимальному прореживанию БД. Спасибо.


 
Sergey13 ©   (2009-10-28 15:48) [12]

> [11] Dim!S   (28.10.09 15:12)

> Форумчане, подскажите кусочек кода по оптимальному прореживанию БД. Спасибо.

delete from tablename
truncate table tablename


 
Сергей М. ©   (2009-10-28 16:07) [13]


> подскажите кусочек кода по оптимальному прореживанию БД


Просто интересно, кто же так густо засадил эту грядку, как часто придется ее прореживать и что потом делать с урожаем ?


 
Dim!S   (2009-10-28 16:42) [14]

действительно интересно? ;)

Необходимо часть сведений из бд убирать... Варианты есть разные... один из них - регулярное копирование и прореживание бд (хотя уже нарисовался и другой путь, но всё же интересно как реализовать алгоритм для указанной задачи по приведённому варианту)... область раскрывать не буду, цель, думаю, понятна... ;)

По теме можете что сказать?


 
Sergey13 ©   (2009-10-28 16:58) [15]

> [14] Dim!S   (28.10.09 16:42)

Все таки не прочитал ты статью по ссылке. Жаль.


 
Сергей М. ©   (2009-10-28 17:10) [16]


> Необходимо часть сведений из бд убирать


Так вот и интересно, по какому критерию требуется осуществлять "прореживание" ?

Четыре очередные морковки дергаем, следующую пятую оставляем, пока либо не подрали всю грядку либо количество этих телодвижений (4 дернули, одну оставили) не превысило 10000,
так что ли ?)


 
Dim!S   (2009-10-28 17:16) [17]

"все таки не прочитал ты статью по ссылке. Жаль" - прочитал... :) про x, y, z ... :) занятно...

отбор будет по критерию 4 выдернули одну оставили из всей таблицы. Возможно условие отбора будет изменено, но мне главное как корректно пройти всю таблицу на предмет прореживания. Пусть будет и не 4 выдернули одну оставили, а по условию проверки значения поля через if c несколькими ветками - неважно, главное как проредить всю таблицу - быстро и корректно.

Спасибо.


 
Сергей М. ©   (2009-10-28 17:36) [18]

счетчик_последовательно_выдернутых_морковок = 0

подойти к началу грядки;

пока не конец грядки делать
начало
  если счетчик_последовательно_выдернутых_морковок < 4 то
  начало
    выдернуть морковку (нос при этом автоматически уткнется или в следующую морковку или в конец грядки)
    увеличить  счетчик_последовательно_выдернутых_морковок на 1
  конец
  иначе
  начало
     счетчик_последовательно_выдернутых_морковок = 0
     передвинуть нос к возможной следующей морковке
 конец
конец


 
Dim!S   (2009-10-28 17:51) [19]

:) ок, получается:
с использованием IBTable

procedure DelRec;
var cnt_Rec: longint; //наврядли будет больше 2 млрд. записей :)
begin
with IBTable do
  begin
      First;

      cnt_Rec := 0;

      while not(EOF) do
           if cnt_Rec < 4 then
              begin
                 if EOF then Break; //а вдруг конец таблицы достигнем в цикле (спасибо Сергей М. за подсказку)

                 Delete;
                 Inc(cnt_Rec);
              end else
              begin
                 cnt_Rec := 0;
                 Next;
              end;
  end;
end;

Интересует как это всё завернуть в транзакции, где ставить StartTransaction и Commit?

Как реализовать это через IBQuery (и надо ли? будет ли какой-то выигрыш от перехода на IBQuery, если бд будет обрабатываться на сервере)?


 
Виталий Панасенко(дом)   (2009-10-28 18:16) [20]

странный вопрос... где тебе нужно, там и ставь.. только от Out of memory На больших НД это тебя вряд ли спасет


 
Dim!S   (2009-10-28 18:20) [21]

Сколько можно максимум обработать (удалить) записей за одну транзакцию? Как обойти ошибку Out Of Memory на больших НД? Наврядли нужно каждую запись удалять через транзакцию - слишком накладно будет...


 
Виталий Панасенко(дом)   (2009-10-28 18:23) [22]

вот именно, накладно...


 
Виталий Панасенко(дом)   (2009-10-28 18:37) [23]

обойти нехватку памяти.. попробуй Unidictional=True, добавить памяти, увеличить своп


 
Dim!S   (2009-10-28 18:45) [24]

Unidirectional=True - как я понял при удалении записей некорректно себя ведёт IBTable c этим параметром в true... Скачет по таблице не по порядку или я заблуждаюсь...


 
Dim!S   (2009-10-28 18:51) [25]

памяти добавлять не вариант и так 2 гига, да и не верный это путь... надо с алгоритмом мудрить чтобы не зависело от аппаратной части...

Я правильно понимаю что большой НД (больше 100 тыс. записей (ну ещё кол-во и тип полей нужно учитывать)) нельзя пройти за раз в цикле на удаление?
Неужели нельзя удалить из базы все записи кроме некоторых (по условию)? - что-то мне подсказывает что можно, но мой уровень общения с firebird не говорит как это сделать...


 
sniknik ©   (2009-10-28 19:26) [26]

> - прочитал... :) про x, y, z ... :) занятно...
ага.
- вы алгебру вообще читали?
- читал, а как же, ее еще в конце убили...

на на свою ситуацию эти x, y, z переложить не в силах? ведь один в один все получается... если счас сказать как-же все таки сделать, то пойдешь ты радостно доделывать своего монстра (и как там дальше по тексту?)
а запросы (правильный z путь) попросту игнорируешь (не понимаешь что это/понимаешь неправильно, а считаешь что совет неправильный, и т.д. неважно по какой причине, но сделал вид, что никто ничего про них не говорил... точно как в статье).


 
Сергей М. ©   (2009-10-28 20:17) [27]


>       while not(EOF) do
>            if cnt_Rec < 4 then
>               begin
>                  if EOF then Break; //а вдруг конец таблицы
> достигнем в цикле (спасибо Сергей М. за подсказку)


С какого перепугу этот "а вдруг" может приключиться ?


 
SergP ©   (2009-10-28 21:10) [28]


> Пусть будет и не 4 выдернули одну оставили, а по условию
> проверки значения поля через if c несколькими ветками -
> неважно, главное как проредить всю таблицу - быстро и корректно.
>


А не проще используя SQL-запрос
типа delete from table where [твое условие]
?


 
Amoeba ©   (2009-10-29 01:20) [29]


> А не проще используя SQL-запрос
> типа delete from table where [твое условие]

И не просто проще, а только так и не иначе.


 
Германн ©   (2009-10-29 01:39) [30]


> Есть бд на Firebird 1.5

Были какие-то похожие глюки с 1.5.
Стоит поискать на ibase.ru сведения о багах версий 1.5.x

P.S. Но все предыдущие замечания знатоков работы с БД, я не отрицаю.


 
PEAKTOP ©   (2009-10-29 02:33) [31]

Весело здесь у вас, ребята...
Не, ну правда.

Топикстартер задает вопрос, почему его велосипед с квадратными колесами не едет ? При этом все дружно начинают давать советы, вплоть до того, что мол попробуй треугольные колеса или пятиугольные.

На 12(!) посте была попытка намекнуть на то, что пора бы уже открыть для себя SQL-оператор DELETE, но все присутствующие ее упорно игнорируют и продолжают рассматривать варианты с шести и семиугольными колесами...

На 29(!) посте наконец-то кому-то все-таки приходит мысль: о, блин, точно ! оператор DELETE! Но это не останавливает участников обсуждения и рассматривается вариант: а может на велосипед поставить гусеницы ? а то с колесами у него говорят баги...

Я фигею, дорогая редакция...  :(


 
Германн ©   (2009-10-29 02:43) [32]


> PEAKTOP ©   (29.10.09 02:33) [31]
>
> Весело здесь у вас, ребята...
> Не, ну правда.

"Дорогая передача!
Во субботу, тут, не плача
Вся Канатчикова дача..."
И т.д.
Тем и живём. :)
На "исходниках" уж очень скушно. А на Королевстве - всё зашорено.


 
Dim!S   (2009-10-29 03:02) [33]

1.         if cnt_Rec < 4 then
             begin
                if EOF then Break; //а вдруг конец таблицы достигнем в цикле (спасибо Сергей М. за подсказку)

                Delete;
                Inc(cnt_Rec);
             end else
             begin
                cnt_Rec := 0;
                Next;
             end; //после этого места возвращаемся к началу ветки if
и пытаемся удалить очередные 4 записи

На деле будет такая ситуация:
в таблице 8 записей
после первого прохода осталось 4 записи курсор встал на 2 запись;
во время второго прохода после удаления 4 записи (2 шаг цикла) мы пытаемся удалить 5 - не существующую запись! - получаем ошибку. Для исключения ошибочной ситуации и проверяем остижение конца таблицы...

2. ну так я ещё в первм посте писал "Может лучше через IBQuery ии есть более изящный способ?" - но конкретного ответа не получил, а именно:

"Интересует как это всё завернуть в транзакции, где ставить StartTransaction и Commit?

Как реализовать это через IBQuery (и надо ли? будет ли какой-то выигрыш от перехода на IBQuery, если бд будет обрабатываться на сервере)?"

3. Чем всё-таки плох IBTable в данной ситуации по сравнению с IBQuery?

P.S. с удовольствием готов пойти по правильному пути, только зная почему нужно делать так, а не иначе...


 
PEAKTOP ©   (2009-10-29 03:40) [34]

> P.S. с удовольствием готов пойти по правильному пути, только
> зная почему нужно делать так, а не иначе...


пилять...


procedure DeleteRecords;
var
 lkTr :TIBTransaction;
 lkSQL :TIBSQL;
begin
 lkTr := TIBTransaction.Create(nil);
 lkTr.DataBase := IBDataBase1;
 lkTr.Params.Clear;
 lkTr.Params.Add("isc_tpb_consistency");
 lkTr.Params.Add("isc_tpb_write");
 lkSQL := TIBSQL.Create(lkTr);
 lkSQL.DataBase := lkTr.DataBase;
 lkSQL.Transaction := lkTr;
 lkSQL.SQL.Text := "DELETE FROM MYTABLE TB1 WHERE (TB1.FIELD = ...) AND (TB1.FIELD2 = ...)";
 lkTr.StartTransaction;
 try
   lkSQL.ExecSQL;
 except
   Dialogs.MessageDlg("Не удалось удалить ....", mtError, [mbOk],0);
   lkTr.Rollback;
 end;
 if lkTr.InTransaction then
   lkTr.Commit;
 lkTr.Free;  // lkSQL.Free будет вызван автоматически, т.к. его Owner = lkTr
end;


 
PEAKTOP ©   (2009-10-29 03:48) [35]

> Как реализовать это через IBQuery (и надо ли? будет ли какой-
> то выигрыш от перехода на IBQuery, если бд будет обрабатываться
> на сервере)?"


Читать для понимания работы с БД вообще и с особенностями Firebird в часности.
1) http://www.ozon.ru/context/detail/id/97142/
2) http://www.ozon.ru/context/detail/id/2496996/

Когда дойдешь до команд SQL, смотри русскоязычную справку c учетом версий сервера Firebird, некоторые команды в InterBase и в Firebird отличаются, некоторых в InterBase вообще нет, а некторорые появились только в недавних версиях сервера и не будут работать, например, в Firebird 1.5/
http://firebirdsql.su/


 
PEAKTOP ©   (2009-10-29 04:09) [36]

> На "исходниках" уж очень скушно.

А ты на sql.ru в ветку Firebird зайди. Там Delphi никто не знает :)

А на Королевстве - всё зашорено.

Я помню описание сего ресурса данное HORRIFIC-ом в журнале XAKEP спец №4 еще в марте 2000 года: "сразу видно, что проект ведет женщина" и что ресурс развивается в сторону своего полного вырождения.

Кстати, страницей ранее тот же автор предсказывал TORRY.NET долгие лета. Как видно, он оказался прав в обоих случаях.


 
Dim!S   (2009-10-29 04:48) [37]

>PEAKTOP Спасибо за код и книги... Первая у меня есть только под Delphi 4.

Не помню где (постараюсь найти), но при поиске инфы по IBTable встретил, что при работе с локальной БД FireBird этот компонент не хуже IBQuery. Так как имел опыт только с Table (Paradox), то решил его использовать, и при обработке получил out of memory - пришлось обратиться к помощи форума, т.к. не хвататает знаний как использовать IBTransaction с IBTable (тем более с IBQuery). Интересует транзакцию можно поставить на весь проход таблицы (думаю не стоит этого делать) или на какой-то блок (по N записей)...

В приведённом коде транзакция охватывает всю обработку таблицы за один проход, так? Какие могут быть проблемы с большими НД (сотни тысяч записей)?

P.S. Всем большое спасибо, но думаю тема не закрыта :)


 
Inovet ©   (2009-10-29 04:56) [38]

> [37] Dim!S   (29.10.09 04:48)

Тут шикник часто пишет про костыли в АДО Table, Query к IBX это тоже применимо - не пользуйся TIBTable


 
Dim!S   (2009-10-29 05:05) [39]

если перейду к firebird то буду пользоваться только IBQuery (FBPlus - рекомендуют). :)
Есть ли задачи где query не эффективен или мало эффективен по сравнению с table?

P.S. программирование не является приоритетным направлением, есть несколько разработанных локальных БД на paradox... по большей части для души...


 
PEAKTOP ©   (2009-10-29 05:57) [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 никуда не годится).

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


 
Inovet ©   (2009-10-29 06:00) [41]

> [39] Dim!S   (29.10.09 05:05)
> Есть ли задачи где query не эффективен или мало эффективен
> по сравнению с table?

внутри TIBTable в отличии от для Парадокса TTable всё равно вся работа ведётся через SQL запросы, есть TIBDataSet.


 
Dim!S   (2009-10-29 06:23) [42]

Спасибо, в принципе понятно...
Думаю при возникновении задачи с использованием сети буду копать только в сторону query...

И всё же (ради любопытства) как удалить кждую n-ю запись с помощью IBQuery?


 
Сергей М. ©   (2009-10-29 08:15) [43]


> Dim!S   (29.10.09 03:02) [33]


Я надеюсь, ты в курсе, что метод Delete после успешного удаления тек.записи автоматически двигает курсор к следующей существующей записи и, если таковой нет (т.е. достигнут конец НД), взводит флаг EOF ?


 
Sergey13 ©   (2009-10-29 09:01) [44]

> [42] Dim!S   (29.10.09 06:23)
> И всё же (ради любопытства) как удалить кждую n-ю запись с помощью IBQuery?

Так
> [34] PEAKTOP ©   (29.10.09 03:40)

даже код тебе дал. Тебе надо обдумать и модифицировать только фразу WHERE (TB1.FIELD = ...) AND (TB1.FIELD2 = ...). Но для того что бы это сделать надо понять что тебе надо. А ты это упорно скрываешь, как партизан. Чем твое "прореживание" лучше чем например "удалить все данные с датой, меньшей чем начало текущего квартала" например? Как обеспечивается порядок записей в твоей ТТабле?


 
RWolf ©   (2009-10-29 10:04) [45]


> И всё же (ради любопытства) как удалить кждую n-ю запись
> с помощью IBQuery?

Не нужно обращаться к записям таблицы по их порядковому номеру, для реляционных БД это идеологически неверно. Заведи ключевое поле, заполненное уникальными значениями, и делай выборки/изменения/удаления по нужному значению.


 
Dim!S   (2009-10-29 10:11) [46]

"если таковой нет (т.е. достигнут конец НД), взводит флаг EOF" вот про это не знал... :(
Чем твое "прореживание" лучше оно не лучше, оно ДРУГОЕ, а если необходимо чтобы записи остались и до начала текущего квартала?
Порядок записей по ID (автоинкремент).

P.S. прореживать будем по условию (придумаем чего-нибудь), но вариант с удалением каждой кроме N записи интересен гипотетически...


 
Anatoly Podgoretsky ©   (2009-10-29 10:33) [47]


> На 12(!) посте была попытка намекнуть на то, что пора бы
> уже открыть для себя SQL-оператор DELETE, но все присутствующие
> ее упорно игнорируют и продолжают рассматривать варианты
> с шести и семиугольными колесами...

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


 
Dim!S   (2009-10-29 10:50) [48]

Меня разделывать? за что??? :)

"Не нужно обращаться к записям таблицы по их порядковому номеру" - я и не пытаюсь обращаться к записям по их порядковому номеру...
"это по произвольному непредсказуемомм набору" - а разве записи в таблице идут не в порядке в каком они добавлены (без испоьзования сортировки, естественно)?

Ок, путь понятен, осталось снарядиться и можно двигаться по нему...

Всем большое спасибо.


 
RWolf ©   (2009-10-29 11:17) [49]


> а разве записи в таблице идут не в порядке в каком они добавлены
> (без испоьзования сортировки, естественно)?

нет, никаких предположений о порядке хранения записей делать нельзя.


 
Сергей М. ©   (2009-10-29 11:26) [50]


> разве записи в таблице идут не в порядке в каком они добавлены


Нет, не идут.
И не обязаны идти.
Куда их сервер соизволит разместить - там они и будут жить.


 
Anatoly Podgoretsky ©   (2009-10-29 11:33) [51]


> Меня разделывать? за что??? :)

Да не тебя.


 
Dim!S   (2009-10-29 17:19) [52]

Удаление через 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 - ключевое поле второй таблицы

или надо использовать хранимые процедуры? Но в БД я их интегрировать, скорее всего, не смогу (запаролена БД)...


 
Сергей М. ©   (2009-10-29 20:28) [53]


> Dim!S   (29.10.09 17:19) [52]


Так это уже совсем другая грядка и совсем другие морковки)


 
RWolf ©   (2009-10-30 01:33) [54]


> Что-то типа этого:

да, что-то вроде.
только WHERE xx IN (...) .


 
Dim!S   (2009-10-30 07:37) [55]

Именение запроса
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 описать? Как это сделать?
Спасибо.


 
Dim!S   (2009-10-30 07:55) [56]

Пробую в IBExpert 4.5 (самая свежая с сайта)


 
sniknik ©   (2009-10-30 08:01) [57]

> Может надо переменную xx описать? Как это сделать?
поменял вопрос, но не поменял стиль... по статье, ты опять не говоришь "мне надо сделать X", а начинаешь с того, что "как  делать Y?" которое уже следствие твоих умозаключений как делается X, а делать Y бессмысленно, описывать переменную xx глупо, по всем признакам она у тебя уже должна быть, и должна быть не переменной а полем таблицы T1, иначе весь запрос теряет смысл (а то что ты делаешь мы не видим, ты не сказал, мы видим только бессмысленный запрос который к тому же дает неизвестную (не показанную тобой) ошибку).
и что на это можно сказать "Как это сделать?" единственный остающийся рабочий вариант как это делается - приглашается ПРОГРАММИСТ, и говорится ему "напишите программу". вариант самому у ТЕБЯ не получится.


 
Dim!S   (2009-10-30 08:18) [58]

что непонятно?
удалить надо из таблицы T1 записи по определённому условию. НЕ каждую n-ю!

Есть несколько таблиц. В таблице T1 есть поля связанные со справочными по внешнему ключу.

Пример:
TOrders
ID
ShopID
ClientID

TShops
ID
Name

TClients
ID
FIO

Необходимо из TOrder удалить записи конкретного магазина и конкретного клиента. Как сделать это чере запрос не знаю.


 
Dim!S   (2009-10-30 08:19) [59]

в предыдушем посте: T1 заменить на TOrders


 
Sergey13 ©   (2009-10-30 08:53) [60]

> [58] Dim!S   (30.10.09 08:18)

Судя по названиям таблиц ты пишешь какой то DB-вирус или иную вредилку. "Прореживать" таблицу заказов - это знаете ли на статью со ссылкой может потянуть. Причем далеко не интернетовские.


 
Dim!S   (2009-10-30 11:08) [61]

>Sergey13
Я знаю на что может потянуть прореживание заказов ;)
но! почему вы опираетесь на мой пример :) право? смешно... :) кто Вам сказал что будет прореживаться БД торговли или иной сферы?
Я не настолько наивен чтобы лезть в инет с просьбой: помогите почистить торговую базу :) И не связываюсь с "мутными" способами заработка...

Уважаемые форумчане!
Давайте по существу вопроса, пожалуйста...


 
Sergey13 ©   (2009-10-30 11:20) [62]

> [61] Dim!S   (30.10.09 11:08)
> но! почему вы опираетесь на мой пример

А на что опираться? Только на свой телепатор. Больше не на что. Ты же молчишь как партизан.
Зачем вообще тебе нужно удалять записи из и так небольшой таблицы? Тем более по так и не сформулированному тобой условию. Место на диске экономить что ли? Так места на диске после просто удаления записей не прибавится.


 
Anatoly Podgoretsky ©   (2009-10-30 12:32) [63]

> Dim!S  (30.10.2009 11:08:01)  [61]

> И не связываюсь с "мутными" способами заработка...

Все так говорят.


 
sniknik ©   (2009-10-30 13:12) [64]

> что непонятно?
> удалить надо из таблицы T1 записи по определённому условию. НЕ каждую n-ю!
"определённому условию" непонятно.

> Необходимо из TOrder удалить записи конкретного магазина и конкретного клиента. Как сделать это чере запрос не знаю.
а вот это уже конкретное условие... (похоже на Х)
DELETE FROM TOrders WHERE ShopID = (SELECT ID FROM TShops WHERE Name = "конкретный магазин") AND ClientID = (SELECT ID FROM TClients WHERE Name = "конкретный клиент")


 
sniknik ©   (2009-10-30 13:18) [65]

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


 
Dim!S   (2009-10-30 15:28) [66]

Условия выборки для удаления прояснились :)

Меня сначала ввели в заблуждение... На самом деле так:
Фирма разделилась, клиенты тоже поделились, хозяева хотят разделить базу и оставить в "своей" базе проводки только по "своим" клиентам...

Извините, за ввод в заблуждение...

P.S. "Все так говорят." - ну так я не утверждаю что я "белый и пушистый", но пусть в меня кинет камень Честый Человек. Только барон Мюнхгаунзен тоже был честным человеком ;). А с реально мутными делами я не связываюсь... - дороже выйдет...


 
Dim!S   (2009-10-30 15:30) [67]

Забыл...
>sniknik Большое спасибо...

Думаю "плотненько" заняться FireBird. Пора переходить к клиент-серверным платформам :)

P.S. - программирование - не основной мой вид деятельности, но очень интересно...


 
Sergey13 ©   (2009-10-30 15:45) [68]

> [66] Dim!S   (30.10.09 15:28)
> Фирма разделилась, клиенты тоже поделились, хозяева хотят
> разделить базу и оставить в "своей" базе проводки только
> по "своим" клиентам...

Настроить (возможно временно, потом отключить) каскадное удаление по внешним ключам и удалить "не своих" клиентов. Просто в справочнике клиентов. Без всякого дополнительного программирования.


 
Dim!S   (2009-10-30 15:52) [69]

Это идея, но, боюсь, пока сложновато будет разобраться в этом... Если кинете скелет или поподробнее объясните, то займусь этим вариантом...


 
Anatoly Podgoretsky ©   (2009-10-30 16:18) [70]

> Sergey13  (30.10.2009 15:45:08)  [68]

Это если база построена правильно и есть признак свой/чужой (ну это исправимо), но вот что они будут делать, если клиент будет относиться к обеим фирмам и разделить проводки будет непросто.


 
Sergey13 ©   (2009-10-30 16:31) [71]

> [69] Dim!S   (30.10.09 15:52)

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

> [70] Anatoly Podgoretsky ©   (30.10.09 16:18)

Как по мне - я бы вообще ничего не удалял. Мне бы без разницы - ну есть клиент в справочнике, ну есть у него проводки за ПРОШЛЫЕ времена - это никому вроде как не мешает.


 
Anatoly Podgoretsky ©   (2009-10-30 16:35) [72]

> Sergey13  (30.10.2009 16:31:11)  [71]

> но жутко мощная - можно одним запросом всю БД грохнуть.

Надо только ключевой точке ударить, например по OrganisationID с настроеным каскадом.


 
Anatoly Podgoretsky ©   (2009-10-30 16:37) [73]

> Sergey13  (30.10.2009 16:31:11)  [71]

> иначе отвалится запрос с ошибкой.

Хуже, останутся потеряные записи без связей - жуткое дело.


 
Sergey13 ©   (2009-10-30 16:53) [74]

> [73] Anatoly Podgoretsky ©   (30.10.09 16:37)

Это если есть "умозрительные" FK поддерживаемые из клиента. Да, безхозные записи - штука та еще.


 
Anatoly Podgoretsky ©   (2009-10-30 16:57) [75]

Если делать не удаление, а копирование в две базы с учетом бизнес логики, то задача имеет решение, но не всегда бизнес логика доступна или понятно, но по крайней мере это путь без последствий.


 
Dim!S   (2009-10-30 16:57) [76]

Да уж.. записи без связей это тот ещё мусор... и ГЛЮКИ!

Запрос под нужные критерии доработал, условия усложнил, добавил дополнительные критерии... :) Вроде работает, буду тестировать тщательно

Запрос на удаление сотен тысяч записей работает очень шустро..., конечно доп условия замедлили, но IBTable просто помирал на более простом условии...

P.S. база не очень сложная по структуре... несколько лет назад разработана... вроде косяков по ключам нет, но бэкапов наделал с помощью gbak ;)


 
Anatoly Podgoretsky ©   (2009-10-30 16:59) [77]

Продумай вариант с копирование.


 
Sergey13 ©   (2009-10-30 16:59) [78]

> [76] Dim!S   (30.10.09 16:57)
> но бэкапов наделал с помощью gbak ;)

Проверял бекапы то? А то неподнимаемый бекап - это посильнее безхозных записей будет. 8-)


 
Dim!S   (2009-10-30 17:09) [79]

проверю ОБЯЗАТЕЛЬНО, неподнимаемый бэкап - это куча седых волос и ... ;)

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



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

Форум: "Начинающим";
Текущий архив: 2009.12.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.7 MB
Время: 0.006 c
2-1256913703
Serge
2009-10-30 17:41
2009.12.20
Предпросмотр и печать ListView


3-1231686479
Чайник
2009-01-11 18:07
2009.12.20
Метод Locate - проблема с апострофом в строке поиска


15-1256195273
Knight
2009-10-22 11:07
2009.12.20
Напомните, про URL


2-1256941705
_
2009-10-31 01:28
2009.12.20
PChar -> String


15-1255892869
POOP
2009-10-18 23:07
2009.12.20
Как в mathcad e решить линейное уравнение?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский