Решено: SQLite3 + Select

Вопросы программирования и использования среды Lazarus.

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

Petrakoff Sergey
новенький
Сообщения: 33
Зарегистрирован: 08.12.2011 11:42:17

Решено: SQLite3 + Select

Сообщение Petrakoff Sergey »

Имеются две таблицы. В обеих таблицах имеются поля IDKATEGOR (означает категорию товара, тип AutoIncrement).
Нужно чтобы по нажатию категории в DBGrid1, в DBGrid2 выводились бы товары только выбранной категории. Никак не могу сделать.
Пробовал так:

Код: Выделить всё

procedure TForm1.FormShow(Sender: TObject);
begin
  with DM do
  begin
    ConnectKat.DatabaseName:= 'Kategorii.db';
    ConnectKat.Connected:= true;
    QKat.Close;
    QKat.SQL.Clear;
    QKat.SQL.Add('select * from TKategorii');
    QKat.Open;
    ConnectLek.DatabaseName:= 'Lekarstva.db';
    ConnectLek.Connected:= true;
    QLek.Close;
    QLek.SQL.Clear;
    QLek.SQL.Add('select * from Lekarstva where IDKATEGOR='+QKAT.FieldByName('IDKATEGOR').AsString);
    QLek.ExecSQL;
    QLek.Open;
  end;
end;

В DBGrid2 ничего не выводится.
Если сделать, например, запрос в виде

Код: Выделить всё

QLek.SQL.Add('select * from Lekarstva where IDKATEGOR=5'); 

то все отлично выводится. Но мне нужно, чтобы пользователь сам выбирал категорию. Может кто подскажет, как сделать запрос?
Последний раз редактировалось Petrakoff Sergey 23.03.2012 08:58:03, всего редактировалось 1 раз.
Аватара пользователя
Little_Roo
энтузиаст
Сообщения: 639
Зарегистрирован: 27.02.2009 18:56:36
Откуда: Санкт-Петербург

Сообщение Little_Roo »

Petrakoff Sergey писал(а):тип AutoIncrement

Такое поле как AsString быть НЕ может. Приводите к строке IntToStr... или пробовать как ....AsVariant
Ism
энтузиаст
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Сообщение Ism »

Для вставки и обновления лучше использовать запрос с параметрами.
Или вставлять данные через Dataset.Insert Dataset.ApplyUpdates Dataset.CommitRetaining
Petrakoff Sergey
новенький
Сообщения: 33
Зарегистрирован: 08.12.2011 11:42:17

Сообщение Petrakoff Sergey »

Little_Roo писал(а):Такое поле как AsString быть НЕ может. Приводите к строке IntToStr... или пробовать как ....AsVariant

Эти возможности я уже пробовал, еще до того, как обратился в форум. В том то и дело, поля целочисленные, а в запросе компилятор говорит, что нужен тип string.
Ism писал(а):Для вставки и обновления лучше использовать запрос с параметрами.
Или вставлять данные через Dataset.Insert Dataset.ApplyUpdates Dataset.CommitRetaining

Честно говоря, ничего не понял. На данный момент базы как бы "статические", ничего не добавляю, просто хочу вывести что есть.
Аватара пользователя
Little_Roo
энтузиаст
Сообщения: 639
Зарегистрирован: 27.02.2009 18:56:36
Откуда: Санкт-Петербург

Сообщение Little_Roo »

Petrakoff Sergey писал(а):В том то и дело, поля целочисленные, а в запросе компилятор говорит, что нужен тип string.

..... + IntToStr(QKAT.FieldByName('IDKATEGOR').AsInteger)
Так пойдет ?
Petrakoff Sergey
новенький
Сообщения: 33
Зарегистрирован: 08.12.2011 11:42:17

Сообщение Petrakoff Sergey »

Little_Roo писал(а):.... + IntToStr(QKAT.FieldByName('IDKATEGOR').AsInteger)
Так пойдет ?

Код: Выделить всё

Main.pas(55,9) Error: Incompatible types: got "LongInt" expected "AnsiString"


Добавлено спустя 3 минуты 33 секунды:
В DBF делал через индексы.
SQLite3 и SQL запросы только начал изучать. Пока все как в тумане.
Аватара пользователя
Little_Roo
энтузиаст
Сообщения: 639
Зарегистрирован: 27.02.2009 18:56:36
Откуда: Санкт-Петербург

Сообщение Little_Roo »

Petrakoff Sergey писал(а):
Little_Roo писал(а):.... + IntToStr(QKAT.FieldByName('IDKATEGOR').AsInteger)
Так пойдет ?


Объявите переменную

Код: Выделить всё

 var s : string ;//(или ansistring)
......
s :=IntToStr(QKAT.FieldByName('IDKATEGOR').AsInteger);
....
QLek.SQL.Add('select * from Lekarstva where IDKATEGOR= ' + s);
....

Ы ???
Petrakoff Sergey
новенький
Сообщения: 33
Зарегистрирован: 08.12.2011 11:42:17

Сообщение Petrakoff Sergey »

Little_Roo писал(а):
Объявите переменную

Код: Выделить всё

 var s : string ;//(или ansistring)
......
s :=IntToStr(QKAT.FieldByName('IDKATEGOR').AsInteger);
....
QLek.SQL.Add('select * from Lekarstva where IDKATEGOR= ' + s);
....

Ы ???

Так тоже пробовал, то же самое
Аватара пользователя
Little_Roo
энтузиаст
Сообщения: 639
Зарегистрирован: 27.02.2009 18:56:36
Откуда: Санкт-Петербург

Сообщение Little_Roo »

Petrakoff Sergey писал(а):Так тоже пробовал, то же самое

И последний вопрос (который был должен быть первым) - ОСь, версия лазаря и fpc
Какие компоненты используются?
Petrakoff Sergey
новенький
Сообщения: 33
Зарегистрирован: 08.12.2011 11:42:17

Сообщение Petrakoff Sergey »

Little_Roo писал(а):И последний вопрос (который был должен быть первым) - ОСь, версия лазаря и fpc
Какие компоненты используются?

Windows XP SP3, Lazarus-0.9.30, fpc-2.4.2, компоненты: TSQLQuery, TSQLite3Connection, TSQLTransaction, TDatasource, TDBGrid

Добавлено спустя 6 минут 20 секунд:
Думаю дело не в Осях или версиях Lazarus. Может можно через TSqlite3Dataset, вообще не используя SQL запросы, как в DBF, через индексы, но мне хочется через запросы. Так сказать, для саморазвития.
Аватара пользователя
Little_Roo
энтузиаст
Сообщения: 639
Зарегистрирован: 27.02.2009 18:56:36
Откуда: Санкт-Петербург

Сообщение Little_Roo »

Petrakoff Sergey писал(а): Lazarus-0.9.30, fpc-2.4.2

Пробуем обновиться на 0.9.31 и 2.6.0 или выше...
TSQLite3Connection => ZEOS 7
TDBGrid => TRxDBGRID
Но это мои предпочтения в плане безглючной (тьфу-тьфу) работы

Использую FireBird 2.5

Lazarus 0.9.31 r36017 FPC 2.7.1 i386-win32-win32/win64
Petrakoff Sergey
новенький
Сообщения: 33
Зарегистрирован: 08.12.2011 11:42:17

Сообщение Petrakoff Sergey »

В книжках написано (правда для Delphi + BDE), что можно перечислять таблицы в запросе, т.е. делать так

Код: Выделить всё

QLek.SQL.Add('select * from Lekarstva, Kategorii where IDKATEGOR= IDKATEGOR');

Компиляция проходит, при выполнении выдает "No such table: Kategorii" .
Еще в одной книге написано, что можно так:

Код: Выделить всё

QLek.SQL.Add('select * from Lekarstva where IDKATEGOR=(select * from  Kategorii where IDKATEGOR)');
Опять же не для Lazarus и не для SQLite3, а для MySQL. Тоже не проходит.
Little_Roo писал(а):TSQLite3Connection => ZEOS 7
TDBGrid => TRxDBGRID

По-моему, не в этом дело. Задача ведь тривиальная. Вывести данные из подчиненной таблицы по значениям поля в главной таблице. Надо только запрос правильно составить. В чем и проблема. Ладно, будем завтра опять пробовать, гуглить. Хотя сегодня уже "нагуглился" по самое...
Аватара пользователя
Little_Roo
энтузиаст
Сообщения: 639
Зарегистрирован: 27.02.2009 18:56:36
Откуда: Санкт-Петербург

Сообщение Little_Roo »

Petrakoff Sergey писал(а):"No such table: Kategorii" .

В первом посте было TKategorii :shock:
Petrakoff Sergey
новенький
Сообщения: 33
Зарегистрирован: 08.12.2011 11:42:17

Сообщение Petrakoff Sergey »

Little_Roo писал(а):В первом посте было TKategorii

Это описка. Должно быть TKategorii
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Petrakoff Sergey
У Вас там слишком много открытий\закрытий датасетов. :)
1. Один раз открыли таблицу TKategorii и всё, больше её не трогайте.
2. На кнопке оставьте только формирование запроса к таблице Lekarstva.
3. Метод ExecSQL используется только тогда, когда Вам не нужно получать данные. Во всех других случаях этот метод совершенно бессмысленен.

Алгоритм действий:
1. Получить из таблицы TKategorii значение IDKATEGOR текущей строки.
2. Подставить это значение в запрос к Lekarstva в секцию WHERE, не забыв преобразовать в строковый тип (т.к. запрос - это строка ;) ).
3. Открыть запрос методом Open.
Всё. :)

Код: Выделить всё

    QLek.Close;
    QLek.SQL.Clear;
    QLek.SQL.Add('select * from Lekarstva where IDKATEGOR='+QKAT.FieldByName('IDKATEGOR').AsString);
    QLek.Open;

100%-но работающий код. И единственный, который нужен. ;)
Ответить