Форум: "Базы";
Текущий архив: 2006.11.12;
Скачать: [xml.tar.bz2];
ВнизКак узнать тип поля в открытом датасете? Найти похожие ветки
← →
SergP. (2006-09-12 11:07) [0]Имеется ввиду если поле типа number(20,4) то как узнать количество знаков и кол. знаков после точки?
← →
ANB © (2006-09-12 11:34) [1]Никак.
Доставай из словаря.
← →
novill © (2006-09-12 11:40) [2]+1
Такие подробности в датасете обычно не хранятся. надо запрашивать из описания.
← →
SergP. (2006-09-12 11:46) [3]Хм... Мне нужно сделать select из Оракла и потом результат запихнуть в Dbf
Каким образом тогда можно типы полей узнать?
← →
Reindeer Moss Eater © (2006-09-12 11:46) [4]Кол-во знаков после точки = TField.Size
← →
novill © (2006-09-12 11:50) [5]а вам обязательны такие подробности? fieldtype не хватает?
← →
Desdechado © (2006-09-12 12:30) [6]> fieldtype не хватает?
Это результат интерпретации типа поля на клиенте. А для создания NUMERIC, например, его недостаточно. Потому как он может интерпретироваться как ftFloat, ftBCD, ftFmtBCD в зависимости от размерности и точности.
← →
SergP. (2006-09-12 12:40) [7]> [5] novill © (12.09.06 11:50)
> а вам обязательны такие подробности? fieldtype не хватает?
Мне dbf нужно создать той же структуры
← →
ANB © (2006-09-12 12:41) [8]клади строкой и не мучайся. AsString завсегда отработает
← →
Anatoly Podgoretsky © (2006-09-12 14:37) [9]SergP. (12.09.06 12:40) [7]
Оракл и дбф - нереально в общем случае.
← →
SergP © (2006-09-12 14:42) [10]> [9] Anatoly Podgoretsky © (12.09.06 14:37)
> SergP. (12.09.06 12:40) [7]
> Оракл и дбф - нереально в общем случае.
В данном случае случай не общий...
Если учесть то что в выборке я буду использовать только типы (символьный (varchar), числовой (numeric) и дата (дата-время)) то реально.
← →
Anatoly Podgoretsky © (2006-09-12 14:44) [11]Не реально, как ты представишь в дбф numeric или numeric(38,21)
← →
Anatoly Podgoretsky © (2006-09-12 14:45) [12]И также дата-время, кроме того о чем ты вообще говоришь, что такое dbf? Пока это три буквы.
← →
SergP © (2006-09-12 14:49) [13]> [11] Anatoly Podgoretsky © (12.09.06 14:44)
> Не реально, как ты представишь в дбф numeric или numeric(38,
> 21)
А у меня в выборках будут только такие типы, которые нормально представляются в дбф. (например numeric(16,4) или numeric(16,0).
Вобщем на фоксе (экспорт из Оракла в дбф) элементарно делается (в 4 строчки), просто неудобно для работы. хочу на дельфи сделать.
← →
SergP © (2006-09-12 14:51) [14]> [12] Anatoly Podgoretsky © (12.09.06 14:45)
> И также дата-время, кроме того о чем ты вообще говоришь,
> что такое dbf? Пока это три буквы.
Извиняюсь. это DBASE IV.
Надеялся что будет понятно по умолчанию...
А насчет даты-времени - то преоборазуется в дату (с потерей времени) и засунется в дбф.
← →
ANB © (2006-09-12 15:47) [15]
> SergP © (12.09.06 14:51) [14]
DBF то зачем нужен ? Для работы напрямую или импорта в другую БД ?
← →
SergP. (2006-09-12 16:05) [16]> [15] ANB © (12.09.06 15:47)
>
> > SergP © (12.09.06 14:51) [14]
>
> DBF то зачем нужен ? Для работы напрямую или импорта в другую
> БД ?
Для использования в другом (не мной писаном) ПО.
← →
SergP. (2006-09-12 16:11) [17]> [4] Reindeer Moss Eater © (12.09.06 11:46)
> Кол-во знаков после точки = TField.Size
т.е. типа так: ?
procedure CreateDBF(sql,filename:string);
var
FieldDesc:array of packed record
Name:array[1..11] of char; //Имя поля
Typ : char; //тип поля
Res : longint; //резерв, х/з для чего
Len : byte; //общая длина поля
Dec : byte; //число десятичных знаков
Res2: array[1..13] of byte; //еще один резерв
Tag : byte;
end;
...
i:integer;
begin
with TADODataSet.Create(Application) do
try
...
CommandText:=sql;
Open;
SetLength(FieldDesc,FieldCount);
for i:=0 to FieldCount-1 do
begin
...
FieldDesc[i].Len:=Fields[i].DataSize;
FieldDesc[i].dec:=Fields[i].Size;
...
end;
...
finally
free;
end;
end;
← →
ANB © (2006-09-12 16:16) [18]
> SergP. (12.09.06 16:11) [17]
Весьма приближенно получишь. Тогда уж лучше по словарю лазить.
← →
SergP. (2006-09-12 16:31) [19]> [18] ANB © (12.09.06 16:16)
>
> > SergP. (12.09.06 16:11) [17]
>
> Весьма приближенно получишь. Тогда уж лучше по словарю лазить.
По словарю - это как?
из sys.user_tab_cols извлекать, что-ли?
← →
ANB © (2006-09-12 17:04) [20]
> SergP. (12.09.06 16:31) [19]
во. есть мысля.
создаешь на основании своего запроса вьюху, достаешь описания полей из user_tab_cols, качаешь из нее данные, грохаешь вьюху (чтоб не мешалась).
← →
SergP. (2006-09-12 17:12) [21]> [20] ANB © (12.09.06 17:04)
>
> > SergP. (12.09.06 16:31) [19]
>
> во. есть мысля.
> создаешь на основании своего запроса вьюху, достаешь описания
> полей из user_tab_cols, качаешь из нее данные, грохаешь
> вьюху (чтоб не мешалась).
Хм... мысля конечно реальная, но муторная. Оставлю ее на крайний случай, это если по другому никак не получится.
← →
ANB © (2006-09-12 17:21) [22]
> SergP. (12.09.06 17:12) [21]
Эт самый надежный способ. Дернул поля вьюхи, создал дбф. Дернул в цикле саму вьюху - перекачал данные.
← →
ANB © (2006-09-12 17:21) [23]Кстати, покопайся - возможно в оракле шлюз есть. во всяком случае он есть для ms sql.
← →
SergP. (2006-09-12 17:29) [24]По крайней мере TFields.size для varchar показывает длину, а для numeric показывает кол-во символов после точки.
Но вот TFields.Datasize показывает вообще какую-то фигню
← →
Reindeer Moss Eater © (2006-09-12 17:37) [25]Как в том анекдоте:
"Это у твоего папы фигня, а у слона - то что надо"
Какую такую фигню показывает?
← →
SergP. (2006-09-12 17:42) [26]> Какую такую фигню показывает?
эксперименты показали, что:
для полей varchar показывает длину+1
Для numeric показывает общую длину, но не менее 10
← →
SergP. (2006-09-12 17:48) [27]> [26] SergP. (12.09.06 17:42)
> > Какую такую фигню показывает?
>
>
> эксперименты показали, что:
> для полей varchar показывает длину+1
> Для numeric показывает общую длину, но не менее 10
Хотя нет. вру...
для полей varchar показывает длину+1
а для numeric показывает... хм... даже не знаю что... Вобщем фигню...
NUMBER (14,0) показывает 34
NUMBER (6,0) показывает 4
NUMBER (4,0) показывает 4
а общую длину, но не менее 10 - это показывает Displaywidth
← →
ANB © (2006-09-12 17:56) [28]
> varchar
эта, в оракле лучше юзать varchar2
← →
SergP. (2006-09-12 18:02) [29]> эта, в оракле лучше юзать varchar2
там и есть varchar2, просто я неправильно написал на форуме...
← →
SergP. (2006-09-12 18:10) [30]Вобщем как я понял, я могу взять TFields.DisplayWidth
Для NUMBER полей размером от 10 и выше - оно показывает правильно общую длину, а то что для мелких полей показывает 10 -по идее не страшно. просто я завышу размерность поля. Главное чтобы данные влезли...
:-)
← →
SergP. (2006-09-12 18:29) [31]Да и как я понял - DisplayWidth показывает правильно длину NUMBER полей, которые в TFields.DataType идут как ftBCD
а для тех Number , для которых TFields.DataType=ftInteger оно показывает 10 (хм. зато теперь понятно почему, насчет DataSize - тоже уже ясно...)
← →
MsGuns © (2006-09-13 09:25) [32]Я все-таки не понял, почему нельзя решить "проблему" с помощью свойства DataType, Precission... самих полей.
Т.е. при создании таблицы целевой БД поля создаются в датасете точно такими же как в исходной, оракловской таблице.
Думаю, что интерпретацию данных из одной СУБД в другую. вполне можно "поручить" движкам.
← →
ANB © (2006-09-13 13:18) [33]
> как в исходной, оракловской таблице.
Автору, как я понял, нужно не просто перекачать данные из таблицу в таблицу, а выгрузить результат запроса, полями которого могут быть и константы.
← →
Reindeer Moss Eater © (2006-09-13 13:32) [34]Я все-таки не понял, почему нельзя решить "проблему" с помощью свойства DataType, Precission... самих полей.
Видимо потому что в случае TFloatField оба эти свойства бесполезны.
← →
MsGuns © (2006-09-13 15:24) [35]>Reindeer Moss Eater © (13.09.06 13:32) [34]
>Видимо потому что в случае TFloatField оба эти свойства бесполезны.
Мне непонятно, какой может быть значность дроби в float ?
← →
Reindeer Moss Eater © (2006-09-13 17:37) [36]Никакой. TFloatField это плавающая точка.
Фиксированная точка у TBCDField.
Но какое там поле у автора - зависит от движка и параметров его настройки.
← →
SergP. (2006-09-13 18:58) [37]> Я все-таки не понял, почему нельзя решить "проблему" с помощью
> свойства DataType, Precission... самих полей.
Насчет Precission можно поподробнее, а то я этим пока не встречался...
> Автору, как я понял, нужно не просто перекачать данные из
> таблицу в таблицу, а выгрузить результат запроса, полями
> которого могут быть и константы.
Желательно чтобы и такое можно было делать... Но на практике в данной задаче такое не встречается...
Пока написал так (это пока в сыром виде), вроде работает:
procedure CreateDBF(ADOConnect:TADOConnection;sql,filename:string);
procedure WinToDos(var St: string); // перекодирование из WIN в DOS
const
// Кроме перекодировки нужных символов (укр. буквы) - остальное пока фигня (но оно не особо нужно)
WtDTable: string = "0123456789abcdef0123456789abcdef01234567"#$f0"9"#$f2"bcde"#$f4"01"#$f6#$f7"4567 "#$f1"9"#$f3"bcde"#$f5;
var
ch: integer;
begin
for ch:=1 to length(st) do
if ord(st[ch])>=$C0 then
if ord(st[ch])<$f0
then st[ch]:=chr(ord(st[ch]) xor $40)
else st[ch]:=chr(ord(st[ch]) xor $10)
else if ord(st[ch])>127 then st[ch]:=WtDTable[ord(st[ch])-127];
end;
var
DBFHeader:packed record // Заголовок DBF-файла
Version : byte; // Версия
yy,mm,dd : byte; // Дата модификации
MaxRecs : longint; // Кол-во записей
HplusD : word; // Положение первой записи
RecLen : word; // Длина записи
Reserv1 : array[12..27] of byte;
IsIndex : byte; // Наличие привязаного CDX - файла
CodePage : byte; // Кодовая страница
Reserv2 : array[30..31] of byte;
end;
FieldDesc:array of packed record // подзаписи полей
Name:array[1..11] of byte; // Имя поля
Typ : char; // Тип поля
Res1: longint;
Len : byte; // Длина поля
Dec : byte; // Кол-во десятичных знаков
Res2: array[1..13] of byte;
Tag : byte;
end;
i,charcount:integer;
term:byte;
fldname:string;
StrFldValue:string;
begin
with TADODataSet.Create(Application) do
try
DisableControls;
Connection:=ADOConnect;
CommandText:=sql;
Open;
SetLength(FieldDesc,FieldCount);
DBFHeader.RecLen:=1; // Длина записи равна сумме длин полей +1 (признак удаления)
for i:=0 to FieldCount-1 do
begin
fldname:=AnsiUpperCase(Fields[i].DisplayName);
for charcount:=1 to 10 do
if charcount>length(fldname)
then FieldDesc[i].Name[charcount]:=0
else FieldDesc[i].Name[charcount]:=ord(fldname[charcount]);
FieldDesc[i].Name[11]:=0;
case Fields[i].DataType of
ftString: begin
FieldDesc[i].Typ:="C";
FieldDesc[i].Len:=Fields[i].Size;
FieldDesc[i].dec:=0;
end;
ftInteger: begin
FieldDesc[i].Typ:="N";
FieldDesc[i].Len:=10;
FieldDesc[i].dec:=0;
end;
ftBCD: begin
FieldDesc[i].Typ:="N";
FieldDesc[i].Len:=Fields[i].DisplayWidth;
FieldDesc[i].dec:=Fields[i].Size;
end;
ftDateTime:begin
FieldDesc[i].Typ:="D";
FieldDesc[i].Len:=8;
FieldDesc[i].dec:=0;
end;
end; //case
inc(DBFHeader.RecLen,FieldDesc[i].Len);
end; // for i:=0 to FieldCount-1 do
DBFHeader.Version:=3; // Версия DBF-файла (DBASE III/DBASE IV/Foxpro без memo)
DBFHeader.MaxRecs:=RecordCount; // Кол-во записей
DBFHeader.IsIndex:=0; // Индексного файла у нас нет
DBFHeader.CodePage:=$65; // Кодовая страница 866
DBFHeader.HplusD:=SizeOf(FieldDesc[0])*length(FieldDesc)+SizeOf(DBFHeader)+1;
with TFileStream.Create(filename,fmCreate) do
try
WriteBuffer(DBFHeader,SizeOf(DBFHeader));
WriteBuffer(FieldDesc[0],SizeOf(FieldDesc[0])*length(FieldDesc));
term:=13; // конец заголовков
WriteBuffer(term,1);
first;
while not eof do
begin
term:=32; // Запись не помеченая на удаление
WriteBuffer(term,1);
for i:=0 to High(FieldDesc) do
begin
case FieldDesc[i].typ of
"D": StrFldValue:=FormatDateTime("yyyymmdd",Fields[i].asDateTime);
"C": begin
StrFldValue:=Fields[i].AsString;
WinToDos(StrFldValue);
while length(StrFldValue)<FieldDesc[i].Len do StrFldValue:=StrFldValue+" ";
end;
"N": begin
StrFldValue:=FloatToStrF(Fields[i].AsFloat,ffFixed,FieldDesc[i].Len,FieldDesc[i] .Dec);
while length(StrFldValue)<FieldDesc[i].Len do StrFldValue:=" "+StrFldValue;
end;
end;
WriteBuffer(pointer(StrFldValue)^,length(StrFldValue));
end;
next;
end;
term:=26; // конец файла
WriteBuffer(term,1);
finally
free;
end;
finally
free;
end;
end;
По крайней мере поля текстовые, числовые и дата - поля перекидывает в дбф нормально, за исключением изменения размерности в некоторых случаюх в большую сторону...
← →
MsGuns © (2006-09-14 09:38) [38]Дело в том, что тип данных - штука вообще интересная. Разные сервера хранят те же самые "деньги" по-разному.
Именно поэтому в Дельфи разработчики предусмотрели класс TField, который как бы объединяет в себе возможный спектр представления данных в физическом формате, приводит все разнообразие серверных типов данных к некому множеству-знаменателю. Предоставляя "движкам" или провайдерам собственно преобразование "нативных" форматов серверов к "машинному".
Часто все эти Currency, BCD и и т.д. якобы "числовые" данные сервером обрабатываются и сохраняются именно как float (ну не умеет процессор работать с дес.разрядами !), а при извлечении или сохранении округляет их до указанной значности (для денежки - до 4 дробных знаков, для BCD - как указано в дескрипторах таблицы), создавая таким образом иллюзию дес. числа с фиксированной точкой и вводя в заблуждение новичков.
ИМХО, не стОит самому заниматься детальной разработкой каких-то алгоритмов преобразования чисел. Лучше, чем это делают разработчики серверов, у Вас навряд ли получится.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2006.11.12;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.059 c