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

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

18.02.2024, 14:51. Показов 2030. Ответов 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
6849 / 4676 / 1464
Регистрация: 14.04.2014
Сообщений: 20,670
Записей в блоге: 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
6849 / 4676 / 1464
Регистрация: 14.04.2014
Сообщений: 20,670
Записей в блоге: 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,612
21.02.2024, 01:34
Цитата Сообщение от DobryaKaktus Посмотреть сообщение
Так параметры у данных SQL запросов не управляемые ведь, разве это не недостаток? По крайней мере я не понял как изменять значения параметров, если это вообще можно делать.
Не понял. И тип параметра и его значение вполне можно задать.
0
42 / 45 / 6
Регистрация: 21.10.2022
Сообщений: 575
Записей в блоге: 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
9921 / 6457 / 2457
Регистрация: 21.01.2014
Сообщений: 27,405
Записей в блоге: 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
9921 / 6457 / 2457
Регистрация: 21.01.2014
Сообщений: 27,405
Записей в блоге: 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
9921 / 6457 / 2457
Регистрация: 21.01.2014
Сообщений: 27,405
Записей в блоге: 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
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru