[Решено] Многие-ко-многим SQLite
Модератор: Модераторы
[Решено] Многие-ко-многим SQLite
Есть две таблицы в SQLite - Акт_обследования (id_акта, текст_акта) и Сотрдуники (id_сотрудника, ФИО). Один акт могут проводить несколько сотрудников. Как я понимаю, нужна связующая таблица для этих двух. Создал её, поля в ней (id_связи, id_акта, id_сотрудника). Как теперь это дело выводить в Лазарусе? Если через компоненты Data Controls, то, желательно, через DBListBox, поскольку нужен мультиселект. Или стоит создать свой компонент на его основе? Подскажите, в какую сторону идти)
Последний раз редактировалось vert 30.12.2012 05:01:11, всего редактировалось 1 раз.
Как извлекать данные из базы уже разобрались?
Для отображения используйте ListBox ы (у них есть мультиселект?), все операции с базой через запросы.
К сожалению, как это сделать в лазарусе стандартными компонентами подсказать не могу, ибо везде упорно использую ZeosLib, оно проще.
Для отображения используйте ListBox ы (у них есть мультиселект?), все операции с базой через запросы.
К сожалению, как это сделать в лазарусе стандартными компонентами подсказать не могу, ибо везде упорно использую ZeosLib, оно проще.
Хотелось бы, чтобы форма выглядела примерно так:

В левом списке выбираем акт, загружаются данные из бд, в правом списке можно редактировать сотрудников, связанных с этим актом.
Можно, в принципе, сделать грид с чекбоксами вместо списка. Можно ли это проделать без использования запросов, одними датасетами/сорсами?
Да, ипользую SQLite3Dataset и Datasource из стандартной поставки лазаруса. Как бы вы сделали то, что мне нужно, через zeoslib?

В левом списке выбираем акт, загружаются данные из бд, в правом списке можно редактировать сотрудников, связанных с этим актом.
Можно, в принципе, сделать грид с чекбоксами вместо списка. Можно ли это проделать без использования запросов, одними датасетами/сорсами?
Как извлекать данные из базы уже разобрались?
Да, ипользую SQLite3Dataset и Datasource из стандартной поставки лазаруса. Как бы вы сделали то, что мне нужно, через zeoslib?
- alexs
- долгожитель
- Сообщения: 4066
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
vert писал(а):Можно ли это проделать без использования запросов, одними датасетами/сорсами?
Я бы сделал так (это не зависит от компонентов доступа к БД, можно на любых):
Связка мастер-детайл
В мастере список актов
В детайле - прочитал список сотрудников - в запросе подзапрос на exist в 3-й таблице факта привязки сотрудника к акту.
Отображал их через RxDBGrid с переопределённым OnGetCellProps в которым через CheckBox (поле exists запроса) указывал цвет фона
На update событие - запрос на добавление/удаление из 3й таблицы связи между сотрудником и актом
Код минимален - фактически конструкция вида
Код: Выделить всё
procedure TMyForm.RxDBGrid1GetCellProps(Sender: TObject; Field: TField;
AFont: TFont; var Background: TColor);
begin
if MyPeoplesFieldExists.AsBoolean then
Background:=clBlue
end;
Ну и соответсвенно правильно написать запрос на выбор сотрудника и на изменение данных о вхождении сотрудника в акт.
Сделал через CheckListBox.
Код: Выделить всё
type
IntegersArray = Array Of Integer;
...
// Заполнение списка сотрудников
function FillWorkersList: IntegersArray;
var
worker_id, act_id, worker_fio: String;
i, all_workers: Integer;
begin
// Записываем ID акта в переменную
act_id := DMForm.Q_card_acts.FieldByName('id').AsString;
// Очищаем список сотрудников
MainForm.act_workers.Clear;
// Запрашиваем список сотрудников
DMForm.Q_workers.Active:=False;
DMForm.Q_workers.Active:=True;
// Узнаём число сотрудников в БД
with DMForm.Q_temp do
begin
Active:= False;
SQL.Text:= 'SELECT COUNT(*) AS ALL_WORKERS FROM workers';
Active:= True;
all_workers:= FieldByName('ALL_WORKERS').AsInteger;
end;
// Устанавливаем размер массива с ID сотрудников
// соответственно числу сотрудников
SetLength(Result, all_workers);
// Заполняем список сотрудников
i:= 0;
while NOT DMForm.Q_workers.EOF do
begin
// Записываем результаты запроса в переменные
worker_fio:= DMForm.Q_workers.FieldByName('FIO').AsString;
worker_id:= DMForm.Q_workers.FieldByName('id').AsString;
// Добавляем строку с ФИО сотрудника
MainForm.act_workers.Items.Add(worker_fio);
// Заполняем массив с ID сотрудников
Result[i]:= StrToInt(worker_id);
// Проверяем наличие связи с актом
with DMForm.Q_temp do
begin
Active:= False;
SQL.Text:= 'SELECT 1 AS RESULT FROM rel_acts_workers' + ' WHERE id_act=' + act_id + ' AND id_worker=' + worker_id;
Active:= True;
// Если связь есть - отмечаем галочкой
if FieldByName('RESULT').AsBoolean = True then
begin
MainForm.act_workers.Checked[i]:= True;
end;
end;
// Переходим к следующему
i:= i + 1;
DMForm.Q_workers.Next;
end;
end;
// Добавление/удаление связи между актом и сотрудником по onClickCheck
procedure CheckWorkerActRelation(item_id, worker_id: Integer);
var
act_id: String;
begin
act_id:= DMForm.Q_card_acts.FieldByName('id').AsString;
// Проверяем, есть связь или нет
with DMForm.Q_temp do
begin
Active:= False;
SQL.Text:= 'SELECT 1 AS RESULT FROM rel_acts_workers' + ' WHERE id_act=' + act_id + ' AND id_worker=' + IntToStr(worker_id);
Active:= True;
// Если связь есть - удаляем её
if FieldByName('RESULT').AsBoolean = True then
begin
Active:= False;
SQL.Text:= 'DELETE FROM rel_acts_workers WHERE id_worker=' + IntToStr(worker_id) + ' AND id_act=' + act_id;
Active:= True;
end
// Иначе - добавляем связь между актом и сотрудником
else
begin
Active:= False;
SQL.Text:= 'INSERT INTO rel_acts_workers (id_worker, id_act) VALUES('+ IntToStr(worker_id) + ', ' + act_id + ')';
Active:= True;
end;
end;
// Перезагружаем список сотрудников
workers_ids:= FillWorkersList;
MainForm.act_workers.Selected[item_id]:= True;
end;