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

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

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

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 17.08.2013, 12:14   #11
ReportCube
Форумчанин
 
Аватар для ReportCube
 
Регистрация: 11.03.2011
Сообщений: 426
По умолчанию

Всегда для себя считайте, что DBQuerty.ExecSQL - разовая команда для исполнения INSERT, UPDATE и тому подобных. Для SELECT используйте DBQuerty.Open или DBQuerty.Active := True.
ReportCube вне форума Ответить с цитированием
Старый 17.08.2013, 12:41   #12
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

угу, вчера сам до этого додумался =))
Теперь другой вопрос:
Как получить доступ к ячейке DBGrid?
Код:
procedure TMainForm.BuildGrid;
var
  i, iDays, iState: Integer;
  Col: TColumn;
  sID: string;
begin
  iDays := DaysInMonth(DateCombo.Date);
  Grid.Columns.Clear;
  Grid.Columns.RebuildColumns;
  Grid.Columns[0].Visible := False;
  for i := 1 to iDays do
  begin
    Col := Grid.Columns.Add;
    with Col do
    begin
      Col.Title.Alignment := taCenter;
      Col.Title.Caption := IntToStr(i);
    end;
  end;
  DateSeparator := '/';
  if not CalendarTbl.IsEmpty then
  begin
    WorkersTbl.First;
    repeat
      sID := WorkersTbl.Fields[0].AsString;
      DBQuerty.Close;
      DBQuerty.SQL.Clear;
      DBQuerty.SQL.Add('SELECT Calendar.Day, Calendar.State');
      DBQuerty.SQL.Add('FROM Workers INNER JOIN Calendar ON Workers.[ID] = Calendar.[ID]');
      DBQuerty.SQL.Add('WHERE (Calendar.ID=' + sID + ') AND');
      DBQuerty.SQL.Add('( DatePart("m",Calendar.Day) = DatePart("m",#' + FormatDateTime('dd/mm/yyyy', fDate) + '#)');
      DBQuerty.SQL.Add('AND DatePart("yyyy",Calendar.Day) = DatePart("yyyy",#' + FormatDateTime('dd/mm/yyyy', fDate) + '#))');
      DBQuerty.Open;

      if not DBQuerty.IsEmpty then
      begin
        DBQuerty.First;
        repeat
          iDays := DayOfTheMonth(DBQuerty.Fields[0].Value);
          iState := DBQuerty.Fields[1].Value;
          case iState of
            0:
              begin
               
                 Grid.Columns[iDays].Field.Value := 'Не был';
              end;
            1:
              begin
                Grid.Columns[iDays].Field.Value := 'Был';
              end;
            2:
              begin
                Grid.Columns[iDays].Field.Value := 'Не известно';
              end;
          end;

          DBQuerty.Next;
        until DBQuerty.Eof;
      end;

      WorkersTbl.Next;
    until WorkersTbl.Eof;
  end;
  DateSeparator := '.';
end;
Вроде бы правильно, и в гугле везде об этом говорят, но нет.
У меня все ячейки, кроме первого столбца, существуют, только в программе, в БД их нет.
Потому:
Grid.Columns[iDays].Field = nil

Получается, что данные из БД, можно забрать только для какой-то ячейки, не для столбца или всех ячеек.

Как это можно решить?
Человек_Борща вне форума Ответить с цитированием
Старый 17.08.2013, 15:38   #13
ReportCube
Форумчанин
 
Аватар для ReportCube
 
Регистрация: 11.03.2011
Сообщений: 426
По умолчанию

Попробуйте в SELECT включить поле так: IsNull(Calendar.State,3) as State
ReportCube вне форума Ответить с цитированием
Старый 17.08.2013, 16:01   #14
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Кароче лесом через речку этот DBGrid =) Руками через запросы в StringGrid - просто шикарно работает.

Код:
procedure TMainForm.BuildGrid;
var
  i, iDays, iState: Integer;
  sID: string;
begin
  iDays := DaysInMonth(DateCombo.Date);

  Grid.ColCount := Grid.ColCount + iDays - 1;
  Grid.Cells[0, 0] := 'Ô.È.Î.';

  for i := 1 to Grid.ColCount - 1 do
    Grid.Cells[i, 0] := IntToStr(i);

  DateSeparator := '/';
  if not CalendarTbl.IsEmpty then
  begin
    Grid.RowCount := WorkersTbl.RecordCount + 1;
    WorkersTbl.First;
    repeat
      sID := WorkersTbl.Fields[0].AsString;
      Grid.Cells[0, StrToInt(sId)] := WorkersTbl.Fields[1].AsString;
      DBQuerty.Close;
      DBQuerty.SQL.Clear;
      DBQuerty.SQL.Add('SELECT Calendar.Day, Calendar.State');
      DBQuerty.SQL.Add('FROM Workers INNER JOIN Calendar ON Workers.[ID] = Calendar.[ID]');
      DBQuerty.SQL.Add('WHERE (Calendar.ID=' + sID + ') AND');
      DBQuerty.SQL.Add('( DatePart("m",Calendar.Day) = DatePart("m",#' + FormatDateTime('dd/mm/yyyy', fDate) + '#)');
      DBQuerty.SQL.Add('AND DatePart("yyyy",Calendar.Day) = DatePart("yyyy",#' + FormatDateTime('dd/mm/yyyy', fDate) + '#))');
      DBQuerty.Open;

      if not DBQuerty.IsEmpty then
      begin
        DBQuerty.First;
        repeat
          iDays := DayOfTheMonth(DBQuerty.Fields[0].Value);
          iState := DBQuerty.Fields[1].Value;
          case iState of
            0:
              begin
                Grid.Cells[iDays, WorkersTbl.RecNo] := 'Íå áûë';
              end;
            1:
              begin
                Grid.Cells[iDays, WorkersTbl.RecNo] := 'Áûë';
              end;
            2:
              begin
                Grid.Cells[iDays, WorkersTbl.RecNo] := 'Íå èçâåñòíî';
              end;
          end;

          DBQuerty.Next;
        until DBQuerty.Eof;
      end;

      WorkersTbl.Next;
    until WorkersTbl.Eof;
  end;
  DateSeparator := '.';
end;
НОВОЕ

Пытаюсь обновить запись Х в таблице, подход своеобразный, но другого, пока, не знаю
Код:
procedure TMainForm.ppExistBtnClick(Sender: TObject);
var
  sText: string;
  d: TDate;
  Day: Word;
begin
  sText := Grid.Cells[Grid.Col, Grid.Row];
  if (sText <> EmptyStr) then
  begin
    Day := StrToInt(Grid.Cells[Grid.Col, 0]);
    D := RecodeDay(fDate, Day);
    DateSeparator := '/';
    DBQuerty.Close;
    DBQuerty.SQL.Clear;
    DBQuerty.SQL.Add('UPDATE Calendar SET Calendar.State = 1');
    DBQuerty.SQL.Add('WHERE (Calendar.ID = ' + IntToStr(Grid.Row) + ')');
    DBQuerty.SQL.Add('AND (Calendar.Day = #' + FormatDateTime('dd/mm/yyyy', D) + '#)');
    sText := DBQuerty.SQL.Text;
    DateSeparator := '.';
    DBQuerty.Open;
    DBQuerty.Close;
    BuildGrid;
  end;
end;
При открытии ADOQuerty вылетает сообщение, что DBQuerty: CommandText doesn't return result set.

Как мне обновить, удалить запись?

Последний раз редактировалось Человек_Борща; 17.08.2013 в 19:46.
Человек_Борща вне форума Ответить с цитированием
Старый 17.08.2013, 20:30   #15
ReportCube
Форумчанин
 
Аватар для ReportCube
 
Регистрация: 11.03.2011
Сообщений: 426
По умолчанию

Смотрите 11 пост
ReportCube вне форума Ответить с цитированием
Старый 17.08.2013, 20:33   #16
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

ReportCube, пробовал, но толку? Результата нет. Таблица не обновляется или не принимает данные, т.е. та как было: Calendar.State = 0 так и остается.
Тот же запрос в MS Access работает на ура.

Не понимаю как искать ошибку её причину и решение.

Пробовал так:
Код:
var
  sText: string;
  d: TDate;
  Day: Word;
begin
  sText := Grid.Cells[Grid.Col, Grid.Row];
  if (sText <> EmptyStr) then
  begin
    Day := StrToInt(Grid.Cells[Grid.Col, 0]);
    D := RecodeDay(fDate, Day);
    DateSeparator := '/';
    DBQuerty.Open;
    DBQuerty.SQL.Clear;
    //DBQuerty.Edit;
    DBQuerty.SQL.Add('UPDATE Calendar SET Calendar.State = 1');
    DBQuerty.SQL.Add('WHERE (Calendar.ID = ' + IntToStr(Grid.Row) + ')');
    DBQuerty.SQL.Add('AND (Calendar.Day = #' + FormatDateTime('dd/mm/yyyy', D) + '#)');
    sText := DBQuerty.SQL.Text;
    DateSeparator := '.';
    Day:=999;
    day:=DBQuerty.ExecSQL;
    ShowMessage(IntToStr(Day));
Возвращает: 0.

Последний раз редактировалось Человек_Борща; 17.08.2013 в 21:09.
Человек_Борща вне форума Ответить с цитированием
Старый 18.08.2013, 18:58   #17
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Как раз именно в этом толк. А не обновляется возможно потому, что во WHERE не то условие. Лучше параметризированный запрос. Это 1-ое. Calendar.ID точно равен Grid.Row? Сомневаюсь. Это 2-ое. И глазками в db посмотреть, что там. Запрос в Access выполнить - это проверка
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 18.08.2013 в 19:00.
Аватар вне форума Ответить с цитированием
Старый 18.08.2013, 19:49   #18
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Я в тупике!

Как обновлять данные?
Код:
const
  Req = 'UPDATE Calendar SET Calendar.State = 0 WHERE (Calendar.ID = %d) AND (Calendar.Day = #%s#)';
var
  sText: string;
  d: TDate;
  Day: Word;
begin
  sText := Grid.Cells[Grid.Col, Grid.Row];
  if (sText <> EmptyStr) then
  begin
    Day := StrToInt(Grid.Cells[Grid.Col, 0]);
    D := RecodeDay(fDate, Day);
    DateSeparator := '/';
    DBQuerty.SQL.Clear;
    DBQuerty.SQL.Text := Format(Req, [Grid.Row, FormatDateTime('dd/mm/yyyy', d)]);
    sText := DBQuerty.SQL.Text;
    DateSeparator := '.';
    Day := 0;
    day := DBQuerty.ExecSQL;
    if Day <> 0 then
      BuildGrid;
  end;
end;
Day - всегда равно нулю.
В MS access запрос работает нормально.

Цитата:
Calendar.ID точно равен Grid.Row? Сомневаюсь. Это 2-ое. И глазками в db посмотреть, что там. Запрос в Access выполнить - это проверка
1. Что такое параметрический запрос?
2. Да, 100%. Grid строю сам.
3. Выполняется в MS Access на 100%.

Последний раз редактировалось Человек_Борща; 18.08.2013 в 19:51.
Человек_Борща вне форума Ответить с цитированием
Старый 18.08.2013, 20:11   #19
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Код:
AdoQuery.SQL.Text:='UPDATE Calendar SET Calendar.State = 0 WHERE Calendar.ID = :MyId AND Calendar.Day = :MyDate';
AdoQuery.Parameters.ParamByName('MyId').Value:=Grid.Row;  
//На счет Grid.Row большие сомнения, даже если сейчас нормально, в дальнейшем будет плохо, нет гарантии, что счетчик будет совпадать,
//после удаления 100%
AdoQuery.Parameters.ParamByName('MyDate').Value:=d;
AdoQuery.ExecSQL;
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 18.08.2013, 20:31   #20
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Теперь работает. И это странно.
Почему MS Access принимает:
Код:
AND Calendar.Day = #:MyDate#
а ADOQurty нет?

Без #, все работает на ура.

Цитата:
//На счет Grid.Row большие сомнения
Это тестовый проект, учусь работать с БД.
БД не предполагает изменения таблицы Workers из программы.
Таблицу строю сам в StringGrid.

Но все же как быть, если не Grid.Row?
Сделал по имени.

в таблице Workers поле FIO ключевое, без совпадений и пустот
в таблице Calendar, поле FIO ключевое, с совпадениями, без пустых строк
Связка: 1-ко-многим

Последний раз редактировалось Человек_Борща; 18.08.2013 в 20:41.
Человек_Борща вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Календарь sid1868 Общие вопросы Delphi 1 04.05.2011 19:55
Календарь sid1868 Помощь студентам 1 04.05.2011 19:16
БД и календарь torrtik БД в Delphi 2 10.04.2011 19:14
Календарь krikaved Общие вопросы Delphi 2 25.03.2010 22:58
Календарь ruavia3 Microsoft Office Excel 6 16.04.2009 15:32