Здравствуйте. Помогите, измучился уже весь.
Есть TMyRec=record состоящий из полей типов integer, record, set и перечислений. Итого sizeof(TRec)=48
Вопросы в следующем:
1. Как запихнуть переменную такого типа в таблицу?
Пробовал так:
var oc:TMyRec;
with ADOQuery1 do
begin
Active:=false;
SQL.clear;
SQL.add('INSERT INTO tmpTable (col1) VALUES(:col1)');
fs:=TMemoryStream.create;
fs.WriteBuffer(oc,sizeof(oc));
parameters.parambyname('col1').loadfromStream(fs,smReadWrite);
ExecSQL;
fs.free;
end;
Сохраняет, но как выдернуть обратно
2. Какой тип данных использовать для поля таблицы(MSSQLServer2005)?
Использовал и varbinaries, ntext, varchar, но результат один и тот же
3. Как извлечь из БД данные и запихнуть её опять в переменную?
Пробовал так:
with ADOQuery1 do
begin
Active:=false;
SQL.clear;
SQL.add('select * from tmp'); --На самом деле там пока одна запись
active:=true;
GetMem(buff,sizeof(oc)+1);
ADOQuery1.Fields[0].GetData(buff,true);
fs:=TMemoryStream.create;
fs.WriteBuffer(buff,sizeof(oc));
fs.seek(0,soFromBeginning);
fs.readBuffer(oc,sizeof(oc));
fs.free;
end;
Здравствуйте, axiv, Вы писали:
BE>>Используйте packed record. И для вложенной записи тоже. BE>>И заливайте в binary/varbinary via stream.
A>В жизни не думал что это доставит такой гемор. A>Не получается Посмотрите пожалуйста, что и где неправильно делаю
[...skipped...]
A>В базе данных поле для этой переменной использую типа VarBytes A>Коннект с помощью ADO
А вам не кажется, что вообще сохранять запись как одну сущность не совсем верно? Что с ней потом делать-то будете — ни отсортировать, ни условие наложить на набор записей не получится — смысла использования БД и SQL я вообще не вижу.
P.S. Я бы создал таблицу со структурой, аналогичной вашей записи и писал бы отдельные поля, а не запись целиком.
Здравствуйте, FilosOFF, Вы писали:
FOF>Тип поля Image.
Спасибо, именно так(s:=CreateBlobStream(Fields[0],bmRead), сам уже нашел путь.
А тип поля может быть и Text и Image, т.е. тот что IsBlob=true
Почему именно так, не пойму.
По сути CreateBlobStream делает чтение данных используя TCustomADODataSet.GetFieldData, в котором есть дополнительные преобразования, но если Native делаешь false, эти преобразования не должны выполняться.
Так что, почему именно так и только с BLOB полями это происходит не понял.
Здравствуйте, axiv, Вы писали:
A>Здравствуйте. Помогите, измучился уже весь. A>Есть TMyRec=record состоящий из полей типов integer, record, set и перечислений. Итого sizeof(TRec)=48 A>Вопросы в следующем: A> Как запихнуть переменную такого типа в таблицу?
Можно сделать TMyRec=class, затем добавить этому классу методы .Serialize и DeSerialize, которые сохранять/восстанавливать данные в/из текста. В качестве формата можно взять XML.
Альтернативный вариант, как подсказал DarkMaster, сделать тоже из записи класс, добавить в него методы SaveToDataset/LoadFromDataset и реализовать загрузку/восстановление полей из текущей записи датасета.
const len=<Длина то известна заранее>;
type
TOccurence = packed record
case boolean of
True: (
dummy:byte; // для AllInString[0]
VarOcurCount:TVarOcur;
StartDate:TDate;
FinishDate:TDate;
OcurCount:smallint;
OcurVariant:TOcur;
ocDay: TOccurenceDay;
ocWeek: TOccurenceWeek;
ocMonth: TOccurenceMounth;
ocYear: TOccurenceYear;
);
False:(
AllInString:shortstring[len];
);
end;
POccurence=^TOccurence;
...
var o:TOccurence;
begin
ADOQuery1.edit;
ADOQuery1.Fields[0].asstring:=o.AllInString;
ADOQuery1.post;
end;
длина записи нам известна, она меньше 255, можно использовать вариантную запись.
старый проверенный способ , а в базе хранить всё в binary char, дабы не потерять информацию ненароком.