Sybase bcp вводит дату и текст данных в базу данных oracle с помощью sqlldr

#sql #oracle #sql-loader

#sql #Oracle #sql-загрузчик

Вопрос:

Я пытаюсь перенести таблицу из базы данных sybase в базу данных Oracle. Ниже приведена структура моей базы данных sybase.

введите описание изображения здесь

Я использовал bcp для извлечения всех записей. Мои извлеченные записи, как показано ниже —

 1|0.1|1/7/2010 12:00:00 AM|<exm><id>1</id></exm> 
2|0.2|1/8/2010 12:00:00 AM|<exm><id>1</id></exm>
  

Я использую следующую команду sqlldr для вставки записей в базу данных oracle.

 sqlldr 'username/passwd@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost.com)(PORT=1111)))(CONNECT_DATA=(SID=MYSIDE)(SERVER=DEDICATED)))' control=loader.ctl log=mylog.log
  

Это мой файл загрузчика (loader.ctl)

 LOAD DATA 
INLINE '/tmp/bcp_out.txt'
INTO TABLE MY_TABLE
FIELDS TERMINATED BY '|'
TRAILING NULLCOLS
(ID,
VERSION,
DATE,
STATEMENT CHAR(10000))
  

Таблица, созданная в Oracle —
введите описание изображения здесь

Итак, из приведенной выше таблицы мы хотим, чтобы дата, поступающая из sybase, была преобразована в oracle timestamp, а оператор был преобразован в Oracle CLOB.

Не могли бы вы подсказать, какие изменения я должен внести в файл загрузчика для достижения моей цели?

Ответ №1:

Целевая таблица (в Oracle; обратите внимание, что date это недопустимое имя столбца (если оно не заключено в двойные кавычки, но я бы не рекомендовал этого)):

 SQL> desc test
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER
 VERSION                                            VARCHAR2(5)
 DATUM                                              TIMESTAMP(6)
 STATEMENT                                          CLOB

SQL>
  

Управляющий файл (включены образцы данных; вероятно, они будут у вас в отдельном файле; кроме того, я не знаю, что на самом деле представляет 1/7/2010 — это 1 июля или 7 января — формат даты, возможно, потребуется изменить):

 load data 
infile *
replace
into table test
fields terminated by '|'
trailing nullcols
( 
id,
version,
datum "to_date(:datum, 'dd/mm/yyyy hh:mi:ss am')",
statement
)

begindata
1|0.1|1/7/2010 12:00:00 AM|<exm><id>1</id></exm> 
2|0.2|1/8/2010 12:00:00 AM|<exm><id>1</id></exm>
  

Сеанс загрузки и результат:

 SQL> $sqlldr scott/tiger control=test22.ctl log=test22.log

SQL*Loader: Release 11.2.0.2.0 - Production on Uto Lis 13 18:16:41 2020

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Commit point reached - logical record count 1
Commit point reached - logical record count 2
    
SQL> -- you don't have to do that; I'm just showing *what is what* in the timestamp
SQL> alter session set nls_timestamp_format = 'dd.mm.yyyy hh:mi:ss.ff6';

Session altered.

SQL> select * from test;

        ID VERSION DATUM                          STATEMENT
---------- ------- ------------------------------ ------------------------------
         1 0.1     01.07.2010 12:00:00.000000 AM  <exm><id>1</id></exm>
         2 0.2     01.08.2010 12:00:00.000000 AM  <exm><id>1</id></exm>


SQL>
  

Как в другом формате даты:

 SQL> select to_timestamp('1 Mon 2020 12:00:00:000 am', 'dd Mon yyyy hh:mi:ss:ff am') from dual;

TO_TIMESTAMP('1SIJ202012:00:00:000AM','DDMONYYYYHH:MI:SS:FFAM')
---------------------------------------------------------------------------
01.01.20 00:00:00,000000000

SQL>
  

Комментарии:

1. Я создал управляющий файл как ваш, но получаю следующую ошибку в файле журнала — ORA-01950: нет привилегий в табличном пространстве «PORTDATA’

2. Администратор базы данных должен предоставить вам квоту для этого табличного пространства,

3. Извините за это.. С этим разобрались. Также мне интересно узнать, каким должен быть формат даты, если дата наступает как — 1 января 2010 года 12:00:00:000AM

4. Вы бы использовали соответствующую маску формата: dd Mon yyyy hh:mi:ss:ff am

5. Он говорит, что формат даты не распознан. Попробовал MMM вместо Mon и получил ту же ошибку. Есть ли какой-либо другой аспект, на который я могу обратить внимание?

Ответ №2:

Вам действительно нужно, чтобы тип данных oracle был ВРЕМЕННОЙ МЕТКОЙ? Из того, что я вижу, ДАТЫ будет достаточно. В oracle, в отличие от некоторых других СУБД, тип данных ДАТЫ включает время, вплоть до секунды. В oracle ВРЕМЕННАЯ МЕТКА включает дату и время с точностью до наносекунды, а также может иметь варианты часовых поясов.

В документации приведен очень хороший пример работы с датами во входном файле csv. Адаптируя это к вашей ситуации:

 LOAD DATA 
INLINE '/tmp/bcp_out.txt'
INTO TABLE MY_TABLE
FIELDS TERMINATED BY '|'
DATE FORMAT "mm/dd/yyyy hh12:mi:ss AM"
TRAILING NULLCOLS
(ID,
VERSION,
DATE,
STATEMENT CHAR(10000))
  

Дополнительные пояснения к модели формата даты здесь.

Что касается clob, я не могу здесь помочь. Никогда не делал этого сам, но я бы начал с просмотра документов для sqlldr.