Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблема вытаскиваниея информации [D6, MySQL]


Страницы:   1 2 3

Separator ©   (2002-10-21 11:32:00) 

Я использую zeos компоненты.
У меня в базе есть поля под название Par1..ParX типа char(18). В них хранятся числовые данные, т.е. просто набор чисел. Как мне их вытащить???
Вот кусок кода:

var
Ar: array [1..18] of byte;
begin
ZMySqlQuery1.Sql.Clear;
ZMySqlQuery1.Sql("select Par1 from ArcRecv1 where NZap=1"); //NZap - номер записи
ZMySqlQuery1.Open;
Ar:= //Как вытащить???
ZMySqlQuery1.Close
end;


Separator   (2002-10-24 12:39:00) [1]

Огромное спасибо работает, хотя и раньше пытался использовать этот метод, но постоянно какие-то ошибки вылетали.
В общем получилось, даже не использую массив, сразу накладываю всю структуру:

type
PPar= ^TPar;
TPar= packed record
flgTS: byte;
Ckv: single;
Vmin: single;
Vkv: byte;
TimeRecv: cardinal;
TimeUpd: cardinal
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Par: PPar;
St: string;
begin
New(Par);

ZMySqlQuery1.Sql.Text:= "select Par1 from ArcRecv1 where NZap=1";
ZMySqlDatabase1.Connect;
ZMySqlQuery1.Open;
ZMySqlQuery1.Fields.Fields[0].GetData(Par);

Memo1.Lines.Clear;
Memo1.Lines.Add("flgTS: "+IntToStr(Par^.flgTS));
Memo1.Lines.Add("Ckv: "+FloatToStr(Par^.Ckv));
Memo1.Lines.Add("Vmin: "+FloatToStr(Par^.Vmin));
Memo1.Lines.Add("Vkv: "+IntToStr(Par^.Vkv));
Memo1.Lines.Add("TimeRecv: "+IntToStr(Par^.TimeRecv));
Memo1.Lines.Add("TimeUpd: "+IntToStr(Par^.TimeUpd));

Dispose(Par);

ZMySqlQuery1.Close;
ZMySqlDatabase1.Disconnect;
end;


passm   (2002-10-24 12:04:00) [2]

Separator © (24.10.02 11:44)> А попробуй воспользоваться TField.GetData(Buffer: Pointer): Boolean.
...
const
DSize = 18;
type
TDataArray = array[0..Dsize - 1] of Byte;
PDataArray = ^TDataArray;
var
P: PDataArray;
begin
New(P);
Query1FIELD1.GetData(P);
...
Dispose(P)
end;


Separator   (2002-10-24 11:44:00) [3]

В общем получилосьЮ но немного по другому. Я сформировал вот какой запрос:
"select ascii(substring(Par1,1,1)), ascii(substring(Par1,2,1)), ascii(substring(Par1,3,1)), ascii(substring(Par1,4,1)), ascii(substring(Par1,5,1)), ascii(substring(Par1,6,1)), ascii(substring(Par1,7,1)), ascii(substring(Par1,8,1)), ascii(substring(Par1,9,1)), ascii(substring(Par1,10,1)), ascii(substring(Par1,11,1)), ascii(substring(Par1,12,1)), ascii(substring(Par1,13,1)), ascii(substring(Par1,14,1)), ascii(substring(Par1,15,1)), ascii(substring(Par1,16,1)), ascii(substring(Par1,17,1)), ascii(substring(Par1,18,1)) from ArcRecv1 where NZap=1"
Результат достигнут, но вот скорость пострадает и больше памяти требуется


passm   (2002-10-24 09:54:00) [4]

Separator © (24.10.02 07:22)>Например:
Query1.SQL.Text:=
"SELECT CAST(Q1.FIELD1 AS BLOB(18)) AS FIELD1
FROM TABLE1 AS Q1
WHERE Q1.ID = :TABLE1_ID"

Далее при открытии запроса BLOB воспринимается как Binary и можно работать как с вариантным массивом.
P.S. Но это для DB2 - для MySQL испытать нет возможности :\


Separator   (2002-10-24 07:22:00) [5]


> passm © (23.10.02 14:07)

В Fields типа TStringField, как мне это сделать (Cast?) Можешщь привести пример?


Separator   (2002-10-24 06:56:00) [6]


> Andriano © (23.10.02 13:54)

Читай внимательно, я использую MySql базу, он алежит на другом хосте в локалке на Linux машине


passm   (2002-10-23 14:07:00) [7]

Separator © (23.10.02 13:17)> Для хранения информации подобного типа в DB2 есть CHARACTER(N) FOR BIT DATA и BDE возвращает это поле как TBytesField.
Но, если это поле преобразовать в другой строковый тип, например, CAST(T1.FIELD1 AS VARCHAR(13)), то BDE все равно возвращает его как TBytesField.
В связи с этим, попробуй проверить какое поле будет у TQuery - воспользуйся Fields Editor"ом. Если TStringField, то попробуй сделать в запросе CAST, чтобы было TBinaryField или TBytesField. Далее рассматривай TBinaryField.Value: Variant как вариантный массив с числами Byte.


Andriano   (2002-10-23 13:54:00) [8]

После s:=.AsString в s записываются уже неверные данные.
А получить адрес свойства .AsString нельзя - это не переменная.

Слушай, у тебя DBF? Читай её сам напрямую, строго её формат? Так можно переконвертировать её, все #0#9... перевести "09...".


Separator   (2002-10-23 13:35:00) [9]


> Andriano © (23.10.02 13:29)

тоже фигня не работает


Separator   (2002-10-23 13:32:00) [10]

В другом формате нельзя сохранять, это уже давно работающая база, и вытаскивать данные получается без проблем на c++, а вот на дельфях не получается, а мне надо обязательно на дельфях


Andriano   (2002-10-23 13:29:00) [11]

Ой я ляпнул...
Чуть выше не "получаешь Ord(.AsString[i]).", а "StrToInt(.AsString[i])."


Andriano   (2002-10-23 13:25:00) [12]

Никак нельзя получить.
Эти 18 байт вообще не читаются из базы (если с #0).
Сохраняй их в допустим формате, тогда и получить сможешь.
Например .AsString:="012345678901234567". А получаешь Ord(.AsString[i]).
Чем тебя это не устраивает?


Separator   (2002-10-23 13:17:00) [13]

А как это сделать ну хоть в DB2, я немного не понял что там написано <passm © (21.10.02 12:41>


passm   (2002-10-23 13:10:00) [14]

И я тебе об этом... См. <passm © (21.10.02 12:41)>
Уже сталкивался с этим, но в DB2.


Separator   (2002-10-23 13:04:00) [15]

А как это получить??? мне не обязательно как char, мне хоть как, мне нужны все 18 байт или указатель на 1 байт из этих 18


Andriano   (2002-10-23 13:01:00) [16]

Так вот я и говорю, что не получается 18 байт, а получается 0 байт, т.к. CHAR в базе начинается с #0 (кстати #0 или "0"). Delphi получается вообще не сохраняет данные из ячейки.
Это теория - повторяю ещё раз. Можешь проверить.

Ладно, сам проверю...Проверил:


Записать в поле типа CHAR символ #0 нельзя. Точнее можно, но всё что после него и он сам игнорируется (как я и говорил).
Нельзя по крайней мере с помощью .AsString:=...
А если и записал, то опять же с помощью AsString получить нельзя (то что после #0). Всё это из-за того, что приложения (IB и Приложение или BDE и Приложение) обмениваются PCHar-ами.
А вообще, всё логично, CHAR предназначен для хранения строк формата ANSI.


Я проверял на IB.


Separator   (2002-10-23 12:28:00) [17]

Это и так вызывает ошибку AccessViolation. Мнеб получить указатель на памфть, где лежат значения получаемые при запросе. Конкретно, если мой запрос такого типа "select Par1 from ArcRecv1 where NZap=1", то реально в результате получается одна ячейка, в ней лежат 18 байт данных, так вот как получить указатель на первый байт?


Andriano   (2002-10-23 12:08:00) [18]

Я тут недавно натыкался на подводные камни со string.
В Delphi (в отличие от Pascal 7.0) string это тот же PChar (просто Delphi следит за string сам).

Т.е. когда переменной типа string не присвоено ни одного значения. Она ссылается на nil (это незаметно, если не разбираться). Когда присвоить значение, то старая память освобождается (если не nil), выделяется новая и туда записывается новое значение. Представляете, что происходит когда выполняется цикл
типа такого

var s:string;
for i:=1 to 100 do s:=s+" ";

Теперь, как это может относиться к вашему вопросу.
Delphi смотрит на значение ParN, как на PCHar, т.е. до ближайшего #0 (если Par1=#0#8#6#8..., то длина pchar-значения = 0). Освобождает память размером в 1 байт (для случая когда Par1=#0...), куда записывает только #0. Т.е. записывает значение "". потом вы обращаетесь AsString[1] (когда к string с 1, а к PChar с 0, здесь вмешивается Delphi для совместимости со старыми pas), получаете значение 0 (за байтом #0 и сам байт #0 смотреть можно - это не проверяется ). А вот когда AsString[2], то скорее всего AccessViolation, т.к. там уже участок памяти, блокированный не вашим процессом.

Всю эту теорию можно проверить так: Считай запись из таблицы, где Par1,Par2,...,ParN<>0 и твой первоначальный способ должен работать.

Кстати к 6 сообщению, Ord(...AsString[i]) - вообщем правильно тоже, т.к. можно читать данные за концом строки (как в widestring, pchar, так и в string), можете проверить. Просто это может вызвать ошибку AccessViolation.


Separator   (2002-10-23 09:25:00) [19]


> Andriano © (23.10.02 09:12)
Поле Par1 (..13) имеет тип char на 18 байт длиной.


Andriano   (2002-10-23 09:12:00) [20]

Может я чего не догоняю.

Но в самом первом вопросе текст SQL "select Par1 from ArcRecv1 where NZap=1".
Выбирается в набор данных только одно поле "Par1" и обращаетесь к нему, но хотите из него (типа CHAR) вытащить AsString[1], AsString[2], AsString[3]... В нём только AsString[1], а дальше
AccessViolation - всё правильно.

Может вам надо так:
ZMySqlQuery1.Sql.Clear;
ZMySqlQuery1.Sql("select * from ArcRecv1 where NZap=1"); ZMySqlDatabase1.Connect;
ZMySqlQuery1.Open;
for i:= 0 to 17 do //нумеруются данные в наборе с нуля
Ar[i+1]:=Ord(ZMySqlQuery1.Fields.Fields[i].AsString);
ZMySqlQuery1.Close;
ZMySqlDatabase1.Disconnect;
end


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо