Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 создание DBF из пакета Oracle  [new]
Joker_Ya
Member

Откуда:
Сообщений: 186
Задачка такая необходимо создавать из пакета dbf файла (формат dBase IV) на диске (структура dbf файла генерируется по данным из таблиц динамически) и заполнение его данными. Есть ли какие либо родные пакеты которые позволяют создать и работать с Dbf ?
19 сен 05, 05:24    [1888552]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: создание DBF из пакета Oracle  [new]
NB52
Member

Откуда: Н.Новгород
Сообщений: 12
Joker_Ya
Задачка такая необходимо создавать из пакета dbf файла (формат dBase IV) на диске (структура dbf файла генерируется по данным из таблиц динамически) и заполнение его данными. Есть ли какие либо родные пакеты которые позволяют создать и работать с Dbf ?


Получилось у Вас?
И мне пришлось этим заниматься...
Сейчас использую оркл2дбф(структура постоянна), но получается dBase III, а нужен dBase IV - приходится пересохранять(причем пользователям).
Если решили, задачку, поделитесь, как,ПОЖАЛУЙСТА!!!
6 июн 07, 22:27    [4239670]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
ПЕС
Member

Откуда: Сургут
Сообщений: 42
Решил аналогигчную задачу так:
1. создал редактором дбф (полно в сети) пустой файлик правильно формата.
2. подключаюсь нему из оракла через гетероденный сервис (смотри ФАК), и заполняю обычными insert into
7 июн 07, 09:32    [4240414]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
ПЕС
Member

Откуда: Сургут
Сообщений: 42
Joker_Ya
(структура dbf файла генерируется по данным из таблиц динамически


сорри, прочитал невнимательно....
7 июн 07, 09:33    [4240425]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
YAP
Member

Откуда: Киев
Сообщений: 2116
посмотрите
http://citkit.ru/package/jdbf/
7 июн 07, 10:16    [4240658]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
a398
Member

Откуда: отсюда на юг
Сообщений: 354
YAP
посмотрите
http://citkit.ru/package/jdbf/

А есть опыт его использования из JVM оракла?
7 июн 07, 11:04    [4241076]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
YAP
Member

Откуда: Киев
Сообщений: 2116
в продакшене работает уже пару месяцев...
7 июн 07, 11:07    [4241111]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
a398
Member

Откуда: отсюда на юг
Сообщений: 354
YAP
в продакшене работает уже пару месяцев...

о как. не смущает, что оно несколько древнее?
м.б поделишься готовыми хранимками?
7 июн 07, 11:10    [4241130]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: создание DBF из пакета Oracle  [new]
VBR
Member

Откуда:
Сообщений: 79
Как обычно вдруг возникла срочная необходимость генерировать DBF с заданной структурой из Oracle и выкладывать на FTP.

Поиск по форуму дал ссылку на JDBF - http://www.svcon.com/jdbf/index.html
пакет FTP - http://www.oracle-base.com/articles/9i/FTPFromPLSQL9i.php
Дальше:
1) Загрузка JDBF
loadjava -user myuser/mypassword@basa jdbf.jar

2) Java-модуль

create or replace and compile java source named exp_dbf as
import com.svcon.jdbf.DBFWriter; 
import com.svcon.jdbf.JDBField; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.Locale; 
import oracle.sql.BLOB;
import oracle.sql.CLOB;
import oracle.jdbc.OracleTypes;
import java.io.*;
import java.sql.*;
import java.sql.CallableStatement;
import oracle.jdbc.driver.*;
import java.io.StringReader;
import java.util.StringTokenizer;


public class TestDbf { 

   /**
     * Парсит одну csv строку.
     * @param line строка
     * @param p_Delim разделитель
     * @return массив столбцов строки
     */
    private static String[] getRowData(String line,String p_Delim) {
        StringTokenizer st = new StringTokenizer(line, p_Delim, false);
        int n = st.countTokens();
        String[] row = new String[n];
        int cn = 0;
        while (st.hasMoreElements()) {
            row[cn++] = ((String) st.nextElement()).trim();
        }
        return row;
    }



/**
   Конвертирует результат SQL запроса в формат DBASE4
   и возвращает DBASE 4 как temporary BLOB
   По идее этот temporary BLOB надо бы внешним модулем freed using the DBMS_LOB.FREETEMPORARY?

   В параметр format передается структура генерируемой DBF таблицы в виде
    Название поля;тип;размер;кол-во знаков после запятой
    Название поля;тип;размер;кол-во знаков после запятой
    и т.д.
    Типы:
    N - числовой
    D - дата
    C - текстовый
    Например:
    sum;N;9;0
    dat;D,8;0
    msg;C;70;0
 
     * @param query SQL запрос
     * @param format строка заголовка таблицы
     * @return массив столбцов строки

*/

public static BLOB gen_dbf_struct(String query,String format)  throws SQLException, java.io.IOException{ 

   Connection con = null;
   BLOB blob = null;
   OutputStream out = null;
   InputStream in = null;
   String line="";
   Statement stmt = null;
   ResultSet r = null;
   Object rowData[]=null;
   DBFWriter dw=null;
   ResultSetMetaData metaData=null;
   int colCount=0;
   String name,type,size,prec;
   
    try {
      con=new OracleDriver().defaultConnection();
      Locale.setDefault(Locale.ENGLISH); 
      blob = BLOB.createTemporary(con, true, BLOB.DURATION_SESSION);
      out = blob.getBinaryOutputStream();

     //Распарсить format и сгенерить структуру таблицы
      BufferedReader bR = new BufferedReader(new StringReader(format));
      while ((line = bR.readLine()) != null) colCount++;
      JDBField arrfiled[] = new JDBField[colCount]; 
      bR = new BufferedReader(new StringReader(format));
      String[] dataRow;
      int i=0;
      while ((line = bR.readLine()) != null) {
                    dataRow = getRowData(line,";");
                    name=dataRow[0];
                    type=dataRow[1];
                    size=dataRow[2];
                    prec=dataRow[3];
                    arrfiled[i] = new JDBField(name,type.charAt(0),Integer.parseInt(size),Integer.parseInt(prec)); 
                    i++;             
       }
      dw = new DBFWriter(out,arrfiled);
      stmt = con.createStatement();
      r = stmt.executeQuery(query);
      metaData = r.getMetaData();
    
     while (r.next()) {
       rowData = new Object[colCount];
       for (i = 0; i < colCount; i++) {
          switch(metaData.getColumnType(i+1)){
           
                 /*DATE*/ case 91: rowData[i]=r.getDate(i+1);break;
              /*NUMERIC*/ case  2: rowData[i]=Double.valueOf(r.getString(i+1));break;
                          case  3: rowData[i]=Double.valueOf(r.getString(i+1));break;
                          case  8: rowData[i]=Double.valueOf(r.getString(i+1));break;
                          default:  rowData[i]=r.getString(i+1); break;
            }
       }
       dw.addRecord(rowData);
   }

  } catch(Exception ex) { 
          /*
               #sql {rollback};
               String d=ex.getMessage();
               #sql { INSERT INTO logtable (DAT,RESULT,ERRCODE) VALUES (sysdate,:d,1)};              
               #sql {commit};
           */
      } 
     finally{
       if (r != null) r.close();
       if (stmt != null) stmt.close();
       if (out != null) {out.close();}
     //  if(con!=null) con.close();
       try{
       if(dw!=null) dw.close();
              }
       catch(Exception ex) {}
      } 
      return blob;
} 


//Конвертирует результат SQL запроса в формат DBASE4 и возвращает DBASE как temporary BLOB
//По идее этот temporary BLOB надо бы внешним модулем freed using the DBMS_LOB.FREETEMPORARY?
//Принимайте во внимание, что в DBASE есть ограничения на длину названия поля, типы и т.д.
public static BLOB gen_dbf_sql(String query)  throws SQLException, java.io.IOException{ 

   Connection con = null;
   BLOB blob = null;
   OutputStream out = null;
   InputStream in = null;
   String line="";
   Statement stmt = null;
   ResultSet r = null;
   Object rowData[]=null;
   DBFWriter dw=null;
   ResultSetMetaData metaData=null;
   String temp;
   int colCount;
   char type;
    try {
      con=new OracleDriver().defaultConnection();
      stmt = con.createStatement();
      r = stmt.executeQuery(query);
      metaData = r.getMetaData();
      colCount=metaData.getColumnCount();
      JDBField arrfiled[] = new JDBField[colCount]; 
      int size=10;
      for (int i = 0; i < colCount; i++) {
           temp=metaData.getColumnName(i+1);
           switch(metaData.getColumnType(i+1)){
           
                 /*DATE*/ case 91: type='D';size=8;break;
              /*NUMERIC*/ case  2: type='N';size=metaData.getPrecision(i+1)==0?10:metaData.getPrecision(i+1);break;
                          case  3: type='N';size=metaData.getPrecision(i+1)==0?10:metaData.getPrecision(i+1);break;
                          case  8: type='N';size=metaData.getPrecision(i+1)==0?10:metaData.getPrecision(i+1);break;
                          default: type='C';size=metaData.getPrecision(i+1)>253?253:metaData.getPrecision(i+1);break;
           }
           if(temp.length()>9) temp=temp.substring(0,9);
           arrfiled[i] = new JDBField(temp,type,size,0);              
       }
     Locale.setDefault(Locale.ENGLISH); 
     blob = BLOB.createTemporary(con, true, BLOB.DURATION_SESSION);
     out = blob.getBinaryOutputStream();
    
     SimpleDateFormat localTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
     dw = new DBFWriter(out,arrfiled);

     while (r.next()) {
       rowData = new Object[colCount];
       for (int i = 0; i < colCount; i++) {
          switch(metaData.getColumnType(i+1)){
           
                 /*DATE*/ case 91: rowData[i]=r.getDate(i+1);break;
              /*NUMERIC*/ case  2: rowData[i]=Double.valueOf(r.getString(i+1));break;
                          case  3: rowData[i]=Double.valueOf(r.getString(i+1));break;
                          case  8: rowData[i]=Double.valueOf(r.getString(i+1));break;
                          default:  rowData[i]=r.getString(i+1); break;
            }
       }
       dw.addRecord(rowData);
   }

  } catch(Exception ex) { 
         /*
               #sql {rollback};
               String d=ex.getMessage();
               #sql { INSERT INTO logtable (DAT,RESULT,ERRCODE) VALUES (sysdate,:d,1)};              
               #sql {commit};
         */
      } 
     finally{
       if (r != null) r.close();
       if (stmt != null) stmt.close();
       if (out != null) {out.close();}
     //  if(con!=null) con.close();
       try{
       if(dw!=null) dw.close();
       }
       catch(Exception ex) {}
      } 
      return blob;
} 

} 
/


3) Функции-обертки
Конвертирует результат SQL запроса в формат DBASE4 и возвращает DBASE как temporary BLOB
По идее этот temporary BLOB должен быть freed using the DBMS_LOB.FREETEMPORARY
create or replace function java_gen_dbf_sql(p_query in varchar2)
  return BLOB as
  language java name 'TestDbf.gen_dbf_sql(java.lang.String) return blob';
/

Конвертирует результат SQL запроса в формат DBASE4
и возвращает DBASE 4 как temporary BLOB
По идее этот temporary BLOB должен быть freed using the DBMS_LOB.FREETEMPORARY

В параметр format передается структура генерируемой DBF таблицы в виде
Название поля;тип;размер;кол-во знаков после запятой
Название поля;тип;размер;кол-во знаков после запятой
и т.д.
Типы:
N - числовой
D - дата
C - текстовый
Например:
sum;N;9;0
dat;D,8;0
msg;C;70;0

create or replace function java_gen_dbf_struct(p_query  in varchar2,
                                               p_format varchar2)
  return BLOB as
  language java name 'TestDbf.gen_dbf_struct(java.lang.String,java.lang.String) return blob';
/
Пример использования

select 
java_gen_dbf_struct('select name_type,vers,sysdate dat from mytable','pt;C;100;0'||chr(10)||'vers;N;9;0'||chr(10)||'dat;D;8;0')
from dual;

select 
java_gen_dbf_sql('select name_type, convert(name_type,''RU8PC866'') namtype,vers,sysdate dat from mytable')
from dual;

convert(name_type,''RU8PC866'') - если нужен в досовской кодировке

P.S. Лепил быстро, могут быть косяки.
26 фев 09, 11:42    [6862910]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
VBR
Member

Откуда:
Сообщений: 79
Теперь хочу решить обратную задачу.
На вход функции blob c DBF, на выходе ARRAY.
Чтобы можно было работать с DBF типа:
select * from table (cast( java_dbf2oracle(dbf_blob) as dbf_table))
При этом если структура dbf заранее известна, то понятно как делать.
Но хочется на вход подавать dbf любой структуры и обойтись без генерации/drop временных таблиц, типов. Ну и через генерацию xml не хочется.
Подскажите направление, pls.
4 мар 09, 09:45    [6884477]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
Alterling
Member

Откуда:
Сообщений: 180
VBR, если речь про обычные таблицы, то без генерации типов тут явно не обойтись, т.к. когда вы пишете cast(... as dbf_table), структура того, во что вы кастите должна быть известна.
CAST converts one built-in datatype or collection-typed value into another built-in datatype or collection-typed value.

Чисто теоретически, наверное, можно попробовать с помощью anytype сгенерировать тип "на лету", т.е. без явных create/drop. Но во что это выльется и какие ограничения будут на работу с этим типом я сказать не могу.

Поэтому предлагаю вариант - превратить ваш dbf в xml, т.к. под работу с xml с заранее неопределенной структурой можно найти наработки.
4 мар 09, 10:05    [6884546]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
VBR
Member

Откуда:
Сообщений: 79
Alterling, спасибо за ответ.
Но генерацию xml не хочется делать. Медленно.
Я сейчас смотрю в сторону возврата ref cursor из java процедуры.
Для этого надо умудриться сгенерить ResultSet, а дальше уже понятно.
4 мар 09, 10:21    [6884616]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
DimaR
Member

Откуда:
Сообщений: 1570
Alterling
Чисто теоретически, наверное, можно попробовать с помощью anytype сгенерировать тип "на лету", т.е. без явных create/drop. Но во что это выльется и какие ограничения будут на работу с этим типом я сказать не могу.


https://www.sql.ru/forum/actualthread.aspx?tid=84306&hl=%ed%e0%e7%e2%e0%eb+%e8%e7%e2%f0%e0%f9%e5%ed%e8%e5%ec#611108
4 мар 09, 10:33    [6884681]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
VBR
Member

Откуда:
Сообщений: 79
Вообщем решил не возиться с ref cursor и сделал тупую конвертацию DBF в XML.
Во вложении весь java-код, может кому пригодится.
Обертка для DBF2XML
 create or replace function java_dbf2XML(p_dbf in BLOB, p_conv number)
  return CLOB as
  language java name 'TestDbf.DBF2XML(oracle.sql.BLOB, int) return oracle.sql.CLOB';

p_dbf - блоб, содержащий таблицу DBASE 4,
p_conv - если 1, то конвертирует из DOS кодировки.

Проблема - неправильно преобразовывается буква Ш (вместо Ш-?).
Скорее всего надо будет завтра саму JDBF подправить.

К сообщению приложен файл (exp_dbf.jsp - 10Kb) cкачать
4 мар 09, 19:48    [6888575]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
VBR
Member

Откуда:
Сообщений: 79
Поправил Jdbf и все стало работать ок.
Во вложении все необходимое.

К сообщению приложен файл (all.zip - 12Kb) cкачать
5 мар 09, 10:49    [6889967]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: создание DBF из пакета Oracle  [new]
user-visio
Member

Откуда:
Сообщений: 30
VBR,
у меня с буквой Ш такая же проблема
str_con:=Convert(val_str2,'RU8PC866','CL8MSWIN1251');
и что делать?
временно заменил Ш на ш
7 июл 16, 19:47    [19382954]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
-2-
Member

Откуда:
Сообщений: 15330
user-visio
str_con:=Convert(val_str2,'RU8PC866','CL8MSWIN1251');
SQL Reference
Note:
Oracle discourages the use of the CONVERT function in the current Oracle Database release. The return value of CONVERT has a character data type, so it should be either in the database character set or in the national character set, depending on the data type. Any dest_char_set that is not one of these two character sets is unsupported. The char argument and the source_char_set have the same requirements.
user-visio
и что делать?
Полагаться на кодировки при работе со строковыми данными внутри БД не верно. Манипулировать кодированием символов только через бинарные данные.
7 июл 16, 20:25    [19383046]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
user-visio
Member

Откуда:
Сообщений: 30
VBR,
у меня с буквой Ш такая же проблема
str_con:=Convert(val_str2,'RU8PC866','CL8MSWIN1251');
и что делать?
временно заменил Ш на ш
8 июл 16, 08:04    [19383977]     Ответить | Цитировать Сообщить модератору
 Re: создание DBF из пакета Oracle  [new]
user-visio
Member

Откуда:
Сообщений: 30
и конкретно что делать?
8 июл 16, 08:07    [19383988]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить