Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.08.2008, 00:15   #1
Roof
Форумчанин
 
Аватар для Roof
 
Регистрация: 01.02.2007
Сообщений: 785
По умолчанию Удалить 2 записи. ADO...

В таблице имеется поле nomer. Много записей с одинаковым значением в поле nomer. Я удаляю записи. Как удалить сразу две записи с одинаковым значением в поле nomer, если таких записей во всей таблице осталось не белее 2-ух?
Вложения
Тип файла: rar if 2 records v ADO.rar (12.8 Кб, 27 просмотров)
Изо всей благодати
В руках крепко сжатых
Я донесу только капли
Roof вне форума Ответить с цитированием
Старый 16.08.2008, 01:06   #2
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

а сколько их должно остаться после удаления?!
и Вы хотите удалять повторы только одного номера (ну, например, где nomer = "25") или всё повторяющиеся номера?
Serge_Bliznykov вне форума Ответить с цитированием
Старый 16.08.2008, 01:30   #3
Roof
Форумчанин
 
Аватар для Roof
 
Регистрация: 01.02.2007
Сообщений: 785
По умолчанию

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

Например, записи в таблице:
1) 25
2) 25
3) 25
4) 89
5) 89
6) 89
7) 95
8)95
9) 95
Выбрал я запись2 и нажал удалить. Остались записи 1,3,4,5,6,7,8,9
Выбрал я запись5 и нажал удалить. Остались записи 1,3,4,6,7,8,9
Выбрал я запись1 и нажал удалить. Остались записи 4,6,7,8,9 - т.е. с одинаковым значением в поле nomer (25) осталось всего две записи. Мы их обе сразу и удаляем
Вот уже часа три не могу сообразить никак
Изо всей благодати
В руках крепко сжатых
Я донесу только капли

Последний раз редактировалось Roof; 16.08.2008 в 01:37.
Roof вне форума Ответить с цитированием
Старый 16.08.2008, 09:37   #4
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

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

Код:
procedure TForm1.Button3Click(Sender: TObject);
var
  NumCount : integer;
  dbCode : Integer;
  dbNomer : string;

begin

  if Not AdoTable1.Active then Exit; {что таблица открыта}
  if AdoTable1.IsEmpty then Exit {что в таблице есть записи...};
  {берём nomer и Код из текущей записи из AdoTable1}
  dbCode := ADOTable1.FieldByName('Код').AsInteger;
  dbNomer := ADOTable1.FieldByName('nomer').AsString;


  AdoQuery1.SQL.Clear;
  AdoQuery1.SQL.Add('Select count(*) as NumCount from List '+
    ' where nomer = "'+dbNomer+'"');
  AdoQuery1.Open;
  NumCount := AdoQuery1.FieldByName('NumCount').AsInteger;
  AdoQuery1.Close;

  Application.MessageBox(Pchar('количество записей ='+IntToStr(NumCount)),
              'Отладка', MB_OK);
  if NumCount = 0 then {ВООБЩЕ НЕЧЕГО УДАЛЯТЬ,
     в базе нет такого Nomer - сюда попасть не должны, просто доп.защита...}
      Application.MessageBox( 'В базе нет таких номеров! '+#13+#10+'Удалять нечего!', 'Предупреждение', MB_ICONWARNING or MB_OK)
  else
    if NumCount > 2 then begin
       {Удаляем только одну запись
        для простоты взял Ваш код.
        хотя, я бы делал это также через
           AdoQuery - delete from List where Код = dbCode}
       adotable1.DeleteRecords(arCurrent);
       adotable1.edit;
       adotable1.post;
    end
    else begin
       {закроем базу в гриде}
       AdoTable1.Close;
       {удаляем ВСЕ записи с таким номером}
       ADOQuery1.SQL.Clear;
       ADOQuery1.SQL.Add('delete from list '+
           ' where nomer = "'+dbNomer+'"');
       ADOQuery1.ExecSQL; {!! всё, обе записи удалены!}

       {обновим отображение базы в гриде}
       AdoTable1.Open;
    end;
end;
AdoQuery.Connection поставьте AdoConnection1 (как у AdoTable1

p.s. молодец, что проект выложил. да ещё и со своим данными. Я точно не стал бы писать код полностью, если бы не было проекта и таблицы! :-))
Serge_Bliznykov вне форума Ответить с цитированием
Старый 16.08.2008, 10:09   #5
SERG1980
Участник клуба
 
Аватар для SERG1980
 
Регистрация: 28.03.2007
Сообщений: 1,814
По умолчанию

Можно попробовать изменить обработчик нажатия кнопки "Удалить" в вашем проекте
Код:
procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
begin
 adotable1.Filtered:=true;
 adotable1.Filter:='nomer=''25''';//вместо 25 можно вставить окно поиска например edit
 if adotable1.RecordCount>2 then adotable1.DeleteRecords(arCurrent)
 else for i :=1 to adotable1.RecordCount  do
      adotable1.Delete;
 adotable1.Filtered:=false;
 adotable1.edit;
 adotable1.post;
end;
SERG1980 вне форума Ответить с цитированием
Старый 16.08.2008, 11:34   #6
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

SERG1980 - а что, кратко и по делу! мне понравилось!! :-)
единственное, я бы вместо цикла
for i :=1 to adotable1.RecordCount
использовал бы:
adotable1.DeleteRecords(arFiltered) ;
Serge_Bliznykov вне форума Ответить с цитированием
Старый 17.08.2008, 16:02   #7
Roof
Форумчанин
 
Аватар для Roof
 
Регистрация: 01.02.2007
Сообщений: 785
По умолчанию

только вот одна проблема с кодом - курсор в таблице перескакивает на первую запись! Я пытаюсь удалить не первую, а, например, вторую или десятую, а удаляется все время только первая )))))))))
Это, вроде, из-за adotable1.Filtered. Как избавится от такого нежелательного эффекта?))))

Цитата:
p.s. молодец, что проект выложил. да ещё и со своим данными. Я точно не стал бы писать код полностью, если бы не было проекта и таблицы! :-))
- всегда в не очень легких вопросах стараюсь выкладывать проекты, чтобы легче было мне помочь
Изо всей благодати
В руках крепко сжатых
Я донесу только капли

Последний раз редактировалось Roof; 17.08.2008 в 16:07.
Roof вне форума Ответить с цитированием
Старый 17.08.2008, 21:03   #8
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Roof запоминайте позицию перед фильтрацией, потом возращайтесь на неё.
если "Код" - уникальное поле - то запоминайте его, потом AdoTable1.Locate(..)
или через BookMark...
что интересно, попробуйте мой первоначальный вариант с AdoQuery - там вроде этой проблемы нет :-)))
Serge_Bliznykov вне форума Ответить с цитированием
Старый 17.08.2008, 21:20   #9
Minimus
Пользователь
 
Аватар для Minimus
 
Регистрация: 03.08.2008
Сообщений: 43
По умолчанию

Привет, Roof.
Я когда-то решал подобную задачу, только для 3 элементов. Поскольку я не спец в БД я ее решил по наглому - примерно так (иллюстрация на основе твоих исходников).
Код:
procedure TForm1.Button2Click(Sender: TObject);
var
count:integer;
tmp:string;

  procedure DelItem(val:string); //ищем и удаляем последний оставшийся элемент
  begin
    with DataSource1 do
    begin
      DataSet.FindFirst;
      repeat
        if ADOTable1nomer.AsString = tmp then begin DataSet.Delete;break end;
      until not DataSet.FindNext;
      DataSet.FindFirst; //здесь можно установить на нужную позицию
    end
  end;

begin
  count:=0;
  with DataSource1 do
  begin
    tmp:= ADOTable1nomer.AsString;
    DataSet.Delete;
    DataSet.FindFirst;
    repeat       //считаем количество оставшихся элементов
      if ADOTable1nomer.AsString = tmp then count:=count+1;
    until not DataSet.FindNext;
    if count = 1 then DelItem(tmp); //один элемент мы уже удалили!!!
  end;
end;
ЗЫ: почему по наглому? - да потому что происходит выход за пределы таблицы, хотя при этом все нормально работает.(Кстати, то же самое наблюдается и в примерах к Delphi 7).При запуске из-под Delphi будет предупреждение об этом. Ну а если пускать без дельфей - то, естественно, все ОК.

ЗЫ2: Для маленькой таблички этот метод - то что надо. Ну а если захочешь применять для чего-то более или менее грандиозного - лучше делай как Serge_Bliznykov.
бороться и искать
найти и перепрятать.

Последний раз редактировалось Minimus; 17.08.2008 в 23:59. Причина: Добавил комментарии
Minimus вне форума Ответить с цитированием
Старый 18.08.2008, 20:32   #10
Roof
Форумчанин
 
Аватар для Roof
 
Регистрация: 01.02.2007
Сообщений: 785
По умолчанию

2 Serge_Bliznykov - Тебе вообще Огромное спасибо ))))) твой код безупречно работает)))) Я, правда, еще не все в нем понял Но ты и это предусмотрел)))) расписал мне комментариев ))))) Использую именно твой код, да еще и Minimus тоже советует твой использовать )))
А вот с примером SERG1980 мне просто ради интереса разобраться до конца охота.
Посмотрите, пожалуйста, вот я попытался запоминать позицию до фильтрации:
Код:
//обработчик кнопки Удалить
procedure TForm1.Button3Click(Sender: TObject);
var i:integer;
pos: string;
begin
 pos:= adotable1.fieldbyname('код').AsString;
 adotable1.Filtered:=true;
 adotable1.Filter:= 'nomer=' + adotable1.fieldbyname('nomer').AsString;
 adotable1.Locate('код', pos, []);
 if adotable1.RecordCount>2 then adotable1.DeleteRecords(arCurrent)
 else for i :=1 to adotable1.RecordCount  do
      adotable1.DeleteRecords(arCurrent);
 adotable1.Filtered:=false;
 adotable1.edit;
 adotable1.post;
end;
Так вот - удаляет он нужную запись теперь. Но после удаления все равно перескакивает на первую! что еще написать, чтобы перескакивал не на первую, а на одну выше? :-))))

2 Minimus - попробую ))))) спасибо тебе за совет ))))
Изо всей благодати
В руках крепко сжатых
Я донесу только капли

Последний раз редактировалось Roof; 18.08.2008 в 20:41.
Roof вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подскажите как программно удалить все записи Worms БД в Delphi 3 04.03.2008 16:30
Как удалить файл dagarik Общие вопросы Delphi 9 05.12.2007 20:25
Как удалить тему? Умелец Свободное общение 2 28.03.2007 12:13
удалить записи в таблице Dbf. pups БД в Delphi 7 15.12.2006 19:19
как удалить анти вирус( касперский 2006)если она не работает и ее не возможно удалить Alar Общие вопросы Delphi 0 29.10.2006 21:36