[Решено] Многие-ко-многим SQLite

Модератор: Модераторы

[Решено] Многие-ко-многим SQLite

Сообщение vert » 19.12.2012 05:06:57

Есть две таблицы в SQLite - Акт_обследования (id_акта, текст_акта) и Сотрдуники (id_сотрудника, ФИО). Один акт могут проводить несколько сотрудников. Как я понимаю, нужна связующая таблица для этих двух. Создал её, поля в ней (id_связи, id_акта, id_сотрудника). Как теперь это дело выводить в Лазарусе? Если через компоненты Data Controls, то, желательно, через DBListBox, поскольку нужен мультиселект. Или стоит создать свой компонент на его основе? Подскажите, в какую сторону идти)
Последний раз редактировалось vert 30.12.2012 05:01:11, всего редактировалось 1 раз.
vert
новенький
 
Сообщения: 19
Зарегистрирован: 11.11.2012 07:56:26

Re: Многие-ко-многим SQLite

Сообщение Frolik » 19.12.2012 14:53:38

Как извлекать данные из базы уже разобрались?
Для отображения используйте ListBox ы (у них есть мультиселект?), все операции с базой через запросы.
К сожалению, как это сделать в лазарусе стандартными компонентами подсказать не могу, ибо везде упорно использую ZeosLib, оно проще.
Frolik
постоялец
 
Сообщения: 275
Зарегистрирован: 18.08.2011 11:52:32

Re: Многие-ко-многим SQLite

Сообщение alexs » 19.12.2012 21:58:52

Frolik писал(а):Для отображения используйте ListBox

Зачем изобретать велосипед? Почему не использовать стандартный DBGrid?
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Многие-ко-многим SQLite

Сообщение vert » 20.12.2012 04:24:53

Хотелось бы, чтобы форма выглядела примерно так:
Изображение
В левом списке выбираем акт, загружаются данные из бд, в правом списке можно редактировать сотрудников, связанных с этим актом.
Можно, в принципе, сделать грид с чекбоксами вместо списка. Можно ли это проделать без использования запросов, одними датасетами/сорсами?
Как извлекать данные из базы уже разобрались?

Да, ипользую SQLite3Dataset и Datasource из стандартной поставки лазаруса. Как бы вы сделали то, что мне нужно, через zeoslib?
vert
новенький
 
Сообщения: 19
Зарегистрирован: 11.11.2012 07:56:26

Re: Многие-ко-многим SQLite

Сообщение alexs » 20.12.2012 07:50:00

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;

Ну и соответсвенно правильно написать запрос на выбор сотрудника и на изменение данных о вхождении сотрудника в акт.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Многие-ко-многим SQLite

Сообщение vert » 28.12.2012 06:56:53

Сделал через 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;
vert
новенький
 
Сообщения: 19
Зарегистрирован: 11.11.2012 07:56:26


Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: Majestic-12 [Bot] и гости: 2

Рейтинг@Mail.ru