|
Программирование >> Oracle
Глава 9 фикатор и пять значений, связанных с этим идентификатором. Можно использовать следующий тип и таблицу: tkyte@TKYTE816> create or replace type myTableType 2 as table of number(12,2) Type created. tkyte@TKYTE816> create table t 2 (x int primary key, у myTableType) 3 nested table у store as y tab Table created. Управляющий файл будет выглядеть следующим образом: (обратите внимание на использование CONSTANT 5 в конструкции count для вложенной таблицы; она указывает утилите SQLLDR, сколько элементов будет в каждой записи) LOAD DATA INFILE * INTO TABLE t replace fields terminated by , у nested table count (CONSTANT 5) BEGINDATA 1,100,200,300,400,500 2,123,243,542,123,432 3,432,232,542,765,543 После запуска SQLLDR получим: tkyte@TKYTE816> select * from t; X Y 1 MYTABLETYPE(100, 200, 300, 400, 500) 2 MYTABLETYPE(123, 243, 542, 123, 432) 3 MYTABLETYPE(432, 232, 542, 765, 543) Как видите, данные загружены во вложенную таблицу. Отвлекаясь ненадолго от темы SQLLDR, хочу обратить ваше внимание на то, что при загрузке можно обнаружить одно из свойств вложенных таблиц. Я случайно обнаружил, что при повторной загрузке тех же данных в таблицу с помощью SQLLDR получается немного другой результат: tkyte@TKYTE816> host sqlldr userid=tkyte/tkyte control=demo24.ctl SQLLDR: Release 8.1.6.0.0 - Production on Sun Apr 15 12:06:56 2001 Загрузка данных 511 (с) Copyright 1999 Oracle Corporation. All rights reserved. Commit point reached - logical record count 3 tkyte@TKYTE816> select * from t; X Y 1 MABLYPE(2OO, 300, 400, 500, 100) 2 MYTABLETYPE(123, 243, 542, 123, 432) 3 MYTABLETYPE(432, 232, 542, 765, 543) Обратите внимание, что теперь число 100 - последнее в первой вложенной таблице. Это побочный эффект повторного использования пространства в таблице при повторной загрузке. Он может воспроизводиться на других системах или с другим размером блока (а может и - нет, как произошло у меня). Во вложенных таблицах порядок строк не сохраняется, так что не удивляйтесь, если данные во вложенной таблице оказываются не в том порядке, как вы их загружали! Вызов утилиты SQLLDR из хранимой процедуры Если коротко - этого сделать нельзя. SQLLDR - не набор функций, его нельзя вызвать. SQLLDR - это утилита командной строки. Конечно, можно написать внешнюю процедуру на языке Java или С, которая запускает SQLLDR (см. в главе 19 пример хранимой процедуры для выполнения команды операционной системы), но это не то же самое, что вызвать SQLLDR. Загрузка при этом будет происходить в другом сеансе, вне вашей транзакции. Кроме того, придется анализировать полученный в результате журнальный файл, чтобы определить, была ли загрузка успешной и насколько успешной (сколько строк было загружено, прежде чем загрузка была прекращена из-за возникновения ошибок). Я не рекомендую вызвать SQLLDR из хранимой процедуры. Итак, что же делать, если необходимо загрузить данные в хранимой процедуре? Возможны следующие варианты. Написать мини-утилиту SQLLDR на языке PL/SQL. При этом можно использовать либо переменные типа BFILE для чтения двоичных данных, либо пакет UTL FILE для чтения, анализа и загрузки текстовых данных. Этот подход будет продемонстрирован далее. Написать мини- утилиту SQLLDR на языке Java. Это не сложнее, чем создание загрузчика на PL/SQL, поскольку можно использовать многие существующие компоненты Java. Написать SQLLDR в виде функции на С, и вызывать его как внешнюю процедуру- Я представил эти варианты в порядке повышения сложности и производительности. Обычно чем сложнее решение, тем выше его производительность. В нашем случае реализации на языках PL/SQL и Java сравнимы по производительности, а реализация на С Глава 9 будет работать быстрее (но окажется менее переносимой и более сложной в создании и установке). Я люблю простоту и переносимость, поэтому продемонстрирую идею реализации на примере PL/SQL. Удивительно, как просто, оказывается, написать собственный мини-SQLLDR. Например: ops$tkyte@DEV816> create table badlog(ernn varchar2(4000), data varchar2(4000)); Table created. Начнем с таблицы для записей, которые не удалось загрузить. Затем создадим функцию загрузки: ops$tkyte@DEV81 create or replace 2 function load data(p table in varchar2, 3 p cnames in varchar2, 4 p dir in varchar2, 5 p filename in varchar2, 6 p delimiter in varchar2 7 return number default ) Она принимает имя таблицы, в которую должна выполняться загрузка, список имен столбцов в том порядке, в каком они заданы во входном файле, каталог и имя загружаемого файла, а также разделитель данных во входном файле. Функция возвращает количество успешно загруженных записей. Далее идут локальные переменные этой небольшой функции:
Затем мы открываем входной файл. Предполагается загружать простые данные через разделитель, причем длина строк не должна превышать 4000 байт. Это ограничение можно расширить до 32 Кбайт (максимальный размер, поддерживаемый пакетом UTLFILE). Для работы с записями большего размера придется использовать тип данных BFILE и средства пакета DBMS LOB: 19 /* 20 * Открываем файл, 21 * Предполагается, * разделитель. 22 */ 23 l input := из которого считываются данные. что он состоит из простых записей через utl file.fopen(p dir, p filename, r, 4000);
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |