Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.12;
Скачать: CL | DM;

Вниз

Как узнать тип поля в открытом датасете?   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.03 c
1-1159444991
DVM
2006-09-28 16:03
2006.11.12
У TEdit какие то проблемы с маленькой буквой "я"?


2-1161818526
fog
2006-10-26 03:22
2006.11.12
OffsetRgn и TCanvas


8-1144330627
QuickFinder
2006-04-06 17:37
2006.11.12
Параметры Flash-файла


2-1161944511
RomanH
2006-10-27 14:21
2006.11.12
Опять эти MDI-окна


2-1161985394
markers
2006-10-28 01:43
2006.11.12
OverDraw и TreeView