Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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.066 c
15-1161763445
Иксик
2006-10-25 12:04
2006.11.12
Кто-нибудь ставил icq с Internet Explorer 7.0?


2-1161861542
Riply
2006-10-26 15:19
2006.11.12
Помещение св-в класса в процедуры как var параметр.


6-1150873944
skiermax
2006-06-21 11:12
2006.11.12
список портов


15-1161622711
Ученик чародея
2006-10-23 20:58
2006.11.12
Драйвер аппаратного устройства на Java.


1-1159424963
DimonS
2006-09-28 10:29
2006.11.12
FastReport и печать





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский