С Новым годом! Форум программистов, компьютерный форум, киберфорум
Delphi: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.50/8: Рейтинг темы: голосов - 8, средняя оценка - 4.50
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93

Как удалить запись из таблицы, чтобы DBGrid не скакал как конь?

18.02.2024, 14:51. Показов 1993. Ответов 31
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Когда удаляю запись из таблицы, фокус и выбор строки в таблице устанавливается на первую запись, а мне хотелось бы добиться, чтобы выбор и фокус устанавливались на следующую строку, далее например удаляем записи, дошли конца таблицы, теперь фокус и выбор должны перемещаться на предыдущую строку.
В принципе этого я мог добиться когда данных очень мало (которые помещаются в видимую часть DBGrid) с помощью:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
k:=IBQuery1.FieldByName('KEY0').AsInteger; //это содержимое записи, которую будем удалять
if IBQuery1.RecNo <> IBQuery1.RecordCount then // пока не достигли конца
IBQuery1.Next //выбираем следующую строку
else IBQuery1.Prior; //в противном случае выбираем предыдущую
l:=IBQuery1.FieldByName('KEY0').AsInteger; //заносим значение первичного ключа в переменную, которую будем использовать для Locate после удаления записи 
 
 
    IBQuery1.SQL.Clear;
    IBQuery1.SQL.Add('DELETE FROM test_table WHERE KEY0 =:param1');
    IBQuery1.Prepare;
    IBQuery1.ParamByName('param1').AsInteger := k;
    IBQuery1.ExecSQL;
    IBQuery1.SQL.Clear;
    IBQuery1.SQL.Add('SELECT * FROM test_table;');
    IBQuery1.Prepare;
    IBQuery1.Close;
    IBQuery1.Open;
    IBQuery1.Locate('key0',l,[loPartialKey]);
Но это неправильно, а хотелось бы удалять правильно, и чтобы выбор и положение скрола не скакали, т.е. нужна некая синхронизация.
В общем плиз помогите, постарался сформулировать понятно.
Схема связи следующая:
Code
1
IBDatabase1 > IBTransaction1 > IBQuery1 > DataSource1 > DBGrid1 (FireBerd 3.0.10.33601)
п.с. Как вариант подумал не удалять, а помечать на удаление выбранные строки, а потом в качестве сервисной функции, была бы возможность очистить таблицу(ы) от записей помеченных на удаление, но также хотелось бы иметь возможность горячего удаления.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.02.2024, 14:51
Ответы с готовыми решениями:

Как удалить запись в dbgrid?
здравствуйте! есть виртуальный датасет MemTableEh, в него заполняются данные из DataSet. затем по каждой заполненой строке MemTableEh...

Как добавить, изменить, удалить, посмотреть запись в DBGrid?
Привет всем! :) Помогите, пожааааааалуйста. :cry: Дано: 1. на Form1 расположен DBGrid (2 колонки) и кнопки &quot;добавить&quot;,...

Как не удалить запись из таблицы?
Здравствуйте, возникла следующая проблема: при работе с recordset и удалении записи из этого recordset одновременно удаляется и запись из...

31
 Аватар для krapotkin
6847 / 4674 / 1463
Регистрация: 14.04.2014
Сообщений: 20,656
Записей в блоге: 21
19.02.2024, 12:06
Лучший ответ Сообщение было отмечено DobryaKaktus как решение

Решение

да что ж такое
за неделю уже по три раза пишу, что два компонента идут по цене одного, и даже три
зачем пихать все в один, раз за разом вставляя туда один и тот же SQL
оставьте для показа в гриде компонент с SELECT
для удалений/обновлений и других важных штук заведите отдельные.
Тем более если вы пользуетесь IB/FB
там есть IBDataset, куда отлично записываются все нужные SQL

Воспользуйтесь им и удаляйте
dataset1.Delete;
по поводу обновлений данных в гриде нужно
1) отключить связь датасета с контролами
2) запомнить ключевое поле
3) закрыть/открыть
4) по ключу найти запись где стояли до закрытия


Delphi
1
2
3
4
5
6
dataset1.DisableControls;
id := dataset1.FieldByName('id').AsInteger;
dataset1.Close;
dataset1.Open;
dataset1.Locate('id', id, []);
dataset1.EnableControls;
P.S.
для работы с Firebird лучше взять FIBPlus
https://github.com/madorin/fibplus
1
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
19.02.2024, 18:51  [ТС]
Что то у меня не получается нормально обновить DBGrid, после удаления появляется два выделения, первое на следующей записи (так и нужно), а вот второе выделение на первой записи, и получается что если опять нажать кнопку удалить, то удалится первая запись.
При этом, обновление DBGrid я выполняю в IBDataSet, а удаление в IBQuery. IBDataSet не использую для удаления, так как пока не разобрался с параметрами.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
    del:=IBDataSet1.FieldByName('key0').AsInteger;
    IBQuery1.SQL.Clear;
    IBQuery1.SQL.Add('DELETE FROM test_table WHERE KEY0 = :param1');
    IBQuery1.Prepare;
    IBQuery1.ParamByName('param1').AsInteger := del;
    IBQuery1.ExecSQL;
 
    IBDataSet1.DisableControls;
    id:=IBDataSet1.FieldByName('key0').AsInteger;
    IBDataSet1.Close;
    IBDataSet1.Open;
    IBDataSet1.Locate('key0',id,[]);
    IBDataSet1.EnableControls;

П.с. сортировкой ещё не занимался.
0
184 / 37 / 8
Регистрация: 14.04.2019
Сообщений: 238
19.02.2024, 19:01
IBQuery сам по себе - объект "только для чтения".
Лично я использую IBTable , но был многократно за это бит на форуме
0
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
19.02.2024, 19:22  [ТС]
По поводу параметров, если прикрутить к DataSet такой механизм:
Delphi
1
2
3
4
    IBQuery1.SQL.Add('DELETE FROM test_table WHERE KEY0 = :param1');
    IBQuery1.Prepare;
    IBQuery1.ParamByName('param1').AsInteger := del;
    IBQuery1.ExecSQL;
То вылазит ошибка, что мол field'a param1 не существует. Что это ещё за подарочек.
Читал справку на https://www.ibase.ru/ibx/, но не заметил там какие-то особенности с параметрами SQL запроса данной компоненты. Разве что компонента имеет специальные параметры, которые могут быть использованы в запросах. Параметры именуются автоматически, и соответствуют именам столбцов, предваряемые префиксами old_ и new_.
0
184 / 37 / 8
Регистрация: 14.04.2019
Сообщений: 238
19.02.2024, 21:51
Возможно, Prepare рано вызвали. Я, признаться, вообще их никогда явно не вызываю.
0
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
20.02.2024, 08:59  [ТС]
Цитата Сообщение от DedFriend Посмотреть сообщение
Возможно, Prepare рано вызвали. Я, признаться, вообще их никогда явно не вызываю.
Да вроде вызывать нужно именно так, правда скорее всего ExecSQL не нужно, так как в последствии мы вызываем Delete.
Delphi
1
2
3
4
    IBDataSet1.SQL.Add('DELETE FROM test_table WHERE KEY0 = :param1');
    IBDataSet1.Prepare;
    IBDataSet1.ParamByName('param1').AsInteger := del;
    IBDataSet1.Delete;
Хотя, может параметры вообще по другому работают у данного компонента.
0
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
20.02.2024, 12:39  [ТС]
Цитата Сообщение от krapotkin Посмотреть сообщение
P.S.
для работы с Firebird лучше взять FIBPlus
https://github.com/madorin/fibplus
Я установил FIBPlus, но что то на палитре компонентов иконки отображаются не так по ходу.
Также добавил в library путь до:
Code
1
2
3
...20.0\source\FIBPlus
...20.0\source\FIBPlus\Editors
...20.0\source\FIBPlus\Packages
Где мышь зарыта?!


0
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
20.02.2024, 16:27  [ТС]
Разобрался с параметрами IBDataSet1, насколько я понял, параметры он именует сам, соответствующие именам field-ов.
Вот так удаляет, удаляет корректно, но скачет...
1. Что нужно исправить?
2. Правильно ли составлен код?
Delphi
1
2
3
4
5
6
7
8
9
10
    id:=IBDataSet1.FieldByName('key0').AsInteger;
    IBDataSet1.DeleteSQL.Clear;
    IBDataSet1.DeleteSQL.Add('DELETE FROM test_table WHERE KEY0 = :key0');// задать текст запроса
    IBDataSet1.DisableControls;
    IBDataSet1.Close;
    IBDataSet1.Open;
    IBDataSet1.Locate('key0',id,[]);
    IBDataSet1.Delete;
    IBDataSet1.Locate('key0',id,[]);
    IBDataSet1.EnableControls;

3. Плз помогите с постом №3.
4. Плз помогите с постом №8.
0
 Аватар для krapotkin
6847 / 4674 / 1463
Регистрация: 14.04.2014
Сообщений: 20,656
Записей в блоге: 21
20.02.2024, 17:46
все SQL стоит задать не в коде а заранее, в design-time
чем в частности хорош FIBPlus
что вам хватит просто
Delphi
1
IBDataSet1.Delete;
надо в Options только покопаться на тему AutoCommit, RefreshAfterDelete и еще каких-то Refresh, если сразу не пойдет
1
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
21.02.2024, 00:07  [ТС]
Цитата Сообщение от krapotkin Посмотреть сообщение
все SQL стоит задать не в коде а заранее, в design-time
Так параметры у данных SQL запросов не управляемые ведь, разве это не недостаток? По крайней мере я не понял как изменять значения параметров, если это вообще можно делать.

Плиз подскажите почему DBGrid нормально не обновляется в данном примере? на первую запись переходит.
Delphi
1
2
3
4
5
6
7
8
9
10
11
    id:=IBDataSet1.FieldByName('key0').AsInteger;
    IBQuery1.SQL.Clear;
    IBQuery1.SQL.Add('DELETE FROM test_table WHERE KEY0 = :key0');
    IBQuery1.Prepare;
    IBQuery1.ParamByName('key0').AsInteger := id;
    IBQuery1.ExecSQL;
    IBDataSet1.DisableControls;
    IBDataSet1.Close;
    IBDataSet1.Open;
    IBDataSet1.Locate('key0',id,[]);
    IBDataSet1.EnableControls;
0
пофигист широкого профиля
4769 / 3204 / 862
Регистрация: 15.07.2013
Сообщений: 18,609
21.02.2024, 01:34
Цитата Сообщение от DobryaKaktus Посмотреть сообщение
Так параметры у данных SQL запросов не управляемые ведь, разве это не недостаток? По крайней мере я не понял как изменять значения параметров, если это вообще можно делать.
Не понял. И тип параметра и его значение вполне можно задать.
0
42 / 45 / 6
Регистрация: 21.10.2022
Сообщений: 560
Записей в блоге: 2
21.02.2024, 01:42
Плиз подскажите почему DBGrid нормально не обновляется в данном примере? на первую запись переходит.
Потому что сначала удаляется запись id, а потом пытается на неё перейти, но не находит, она же удалена.
1
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
21.02.2024, 09:20  [ТС]
Цитата Сообщение от northener Посмотреть сообщение
Не понял. И тип параметра и его значение вполне можно задать.
Я про то, что метод ParamByName не работает у меня, говорит что не найден такой field, даже если имя параметру задать соответствующее имени field'a. Видимо я не понял что то.
Delphi
1
2
3
    IBDataSet1.SQL.Add('DELETE FROM test_table WHERE KEY0 = :key0');
    IBDataSet1.ParamByName('key0').AsInteger := del;
    IBDataSet1.Delete;
Цитата Сообщение от didgik Посмотреть сообщение
Потому что сначала удаляется запись id, а потом пытается на неё перейти, но не находит, она же удалена.
А как тогда нужно? В смысле я пробовал по разному, у меня не получается добиться нужного эффекта.
0
Модератор
 Аватар для D1973
9908 / 6445 / 2455
Регистрация: 21.01.2014
Сообщений: 27,356
Записей в блоге: 3
21.02.2024, 09:26
Цитата Сообщение от DobryaKaktus Посмотреть сообщение
А как тогда нужно?
Для позиционирования указать номер существующей записи, предыдущей или следующей относительно удаляемой. Предвосхищая вопрос "как?" - почитайте про функцию Locate и подключите голову.
0
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
21.02.2024, 10:04  [ТС]
Цитата Сообщение от D1973 Посмотреть сообщение
Предвосхищая вопрос "как?" - почитайте про функцию Locate и подключите голову.
Я читал про эту функцию, Вы имеете в виду про методы next, prior и last у датасета? оперируя ими, добиться нужного эффекта?
0
Модератор
 Аватар для D1973
9908 / 6445 / 2455
Регистрация: 21.01.2014
Сообщений: 27,356
Записей в блоге: 3
21.02.2024, 10:15
Цитата Сообщение от DobryaKaktus Посмотреть сообщение
Я читал про эту функцию
Ну и что Вы вычитали? Куда будет позиционироваться запись при таком вызове?
Delphi
1
IBDataSet1.Locate('key0',id,[]);
0
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
21.02.2024, 10:21  [ТС]
Цитата Сообщение от D1973 Посмотреть сообщение
Ну и что Вы вычитали? Куда будет позиционироваться запись при таком вызове?
Позиционироваться будет на записи удовлетворяющей критерию поиска, в данном случае критерий, это значение первичного ключа которое я получил ранее вызовом "id:=IBDataSet1.FieldByName('key0').AsIn teger;".

Добавлено через 1 минуту
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    IBDataSet1.DisableControls;
    id:=IBDataSet1.FieldByName('key0').AsInteger;
    IBDataSet1.Close;
    IBDataSet1.Open;
    if IBDataSet1.Locate('key0',id,[]) = true then
    IBDataSet1.Locate('key0',id,[])
      else begin
       if IBDataSet1.Locate('key0',id,[]) = {как узнать что данная запись последняя?} then
       IBDataSet1.Prior
        else
        IBDataSet1.Next;
 
      end;
    IBDataSet1.EnableControls;
Что то типа такого? а как узнать что Locate соответствует последней записи? как это узнать правильно?
0
Модератор
 Аватар для D1973
9908 / 6445 / 2455
Регистрация: 21.01.2014
Сообщений: 27,356
Записей в блоге: 3
21.02.2024, 10:36
Лучший ответ Сообщение было отмечено DobryaKaktus как решение

Решение

Цитата Сообщение от DobryaKaktus Посмотреть сообщение
а как узнать что Locate соответствует последней записи?
А нет такого понятия в общем случае. Все зависит от режима сортировки набора данных. А вообще - проверять набор данных на Eof:
Delphi
1
if IBDataSet.Eof then ...
Добавлено через 2 минуты
Цитата Сообщение от DobryaKaktus Посмотреть сообщение
Что то типа такого?
Вам же уже говорили, что запись, в которой поле "key0" равно значению переменной id Вы уже удалили. Ну так и куда Вы позиционироваться собираетесь?
1
2 / 2 / 0
Регистрация: 30.06.2022
Сообщений: 93
21.02.2024, 11:03  [ТС]
Цитата Сообщение от D1973 Посмотреть сообщение
Ну так и куда Вы позиционироваться собираетесь?
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    del:=IBDataSet1.FieldByName('key0').AsInteger;
    IBDataSet1.DisableControls;
    if IBDataSet1.Eof then
     begin
     IBDataSet1.Prior;
     id:=IBDataSet1.FieldByName('key0').AsInteger;
       end else begin
       IBDataSet1.Next;
       id:=IBDataSet1.FieldByName('key0').AsInteger;
       end;
    IBQuery1.SQL.Clear;
    IBQuery1.SQL.Add('DELETE FROM test_table WHERE KEY0 = :key0');
    IBQuery1.Prepare;
    IBQuery1.ParamByName('key0').AsInteger := del;
    IBQuery1.ExecSQL;
    IBDataSet1.Close;
    IBDataSet1.Open;
    IBDataSet1.Locate('key0',id,[]);
    IBDataSet1.EnableControls;
Вот что у меня получилось, удаляет последовательно записи, но после удаления последней переходит на 1 запись. И скролл скачет
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
21.02.2024, 11:03
Помогаю со студенческими работами здесь

Как удалить запись из таблицы?
Здрасте Уважаемые! У меня проблема возникла, нужно удалить определенную запись из таблицы. Т.е. у меня при открытии формы создается...

Как удалить запись из таблицы? (связи)
Доброго времени суток. Такой вопрос...к примеру есть несколько таблиц: &quot;Клиенты&quot; и &quot;Сотрудники&quot;. Сотрудники являются...

Как мне удалить запись из хеш-таблицы
Добрый день! Имеется хеш-таблица с данными о постояльцах. Поиск осуществляется по номеру паспорта. Метод разрешения коллизий - квадратичное...

Как можно удалить запись из временной таблицы?
подскажите как можно удалить запись из временной таблицы? я сначала создал таблицу потом при ее заполнении получаю список данных, удаляю...

Как удалить выбранную запись из таблицы Access в форме VB ?
Подскажите пожалуйста. У меня есть форма. Есть таблица формата .mdb (Access) . Таблица перенесена в форму в ОЛЕ. В таблице слева я вижу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru