Чтение массивного CSV-файла в таблицу Oracle - PullRequest
0 голосов
/ 03 ноября 2019

У меня есть этот огромный CSV-файл, который содержит более 200 000 строк. каждая строка имеет идентификатор отзыва, идентификатор отеля, дату отзыва и сам отзыв. Столбец обзора вызывает проблемы. Некоторые обзоры очень длинные, длиннее 2000 байт, поэтому они вызывают ошибку:

ORA-20000: ORU-10027: переполнение буфера, ограничение в 20000 байт.

Что я могу сделать, чтобы обойти эту проблему? Вот мой текущий код:

DECLARE
    F UTL_FILE.FILE_TYPE;
    v_Line VARCHAR2(2000);
    v_ReviewID NUMBER;
    v_HotelID VARCHAR2(2000);
    v_ReviewDate VARCHAR(2000);
    v_ReviewName CLOB;
    v_Review CLOB;
BEGIN
    F := UTL_FILE.FOPEN ('REVIEW_READ', 'Review.csv', 'R', 30000);

    IF UTL_FILE.IS_OPEN(F) THEN
        LOOP
            BEGIN
                DBMS_OUTPUT.PUT_LINE('Start');
                UTL_FILE.GET_LINE(F, v_Line);            
                v_ReviewID    := REGEXP_SUBSTR(v_Line, '[^,]+', 1, 1);
                v_HotelID     := REGEXP_SUBSTR(v_Line, '[^,]+', 1, 2);
                v_ReviewDate  := REGEXP_SUBSTR(v_Line, '[^,]+', 1, 3); 
                v_ReviewName  := REGEXP_SUBSTR(v_Line, '[^,]+', 1, 4);
                v_Review      := REGEXP_SUBSTR(v_Line, '[^,]+', 1, 5);

                INSERT INTO Review
                VALUES(v_ReviewID, v_HotelID, v_ReviewDate, v_ReviewName, v_Review);

                DBMS_OUTPUT.PUT_LINE(v_Line);

                IF v_Line IS NULL THEN
                    EXIT;
                END IF;

                COMMIT;
            EXCEPTION
                WHEN NO_DATA_FOUND THEN
                    EXIT;
            END;
        END LOOP;
    END IF;
EXCEPTION  
    WHEN OTHERS THEN  
        dbms_output.put_line(SQLERRM);
        UTL_FILE.FCLOSE(F);
END;

Ответы [ 3 ]

4 голосов
/ 03 ноября 2019

Есть 2 проблемы с вашим кодом. Один из них уже упоминался @Steve Friedl. А другой, как показано ниже:

ORU-10027 появится, если вы используете много dbms_output.put_line в вашем PL/SQL с небольшим количеством буфера. Если вы просто отлаживаете, вам следует установить это значение на большое значение (dbms_output.enable (10000000) является традиционным, хотя начиная с 10g это может быть не ограничено.

Так что в вашем коде, если вы прокомментируете эту строку DBMS_OUTPUT.PUT_LINE(V_LINE);и выведите это DBMS_OUTPUT.PUT_LINE('Start'); из цикла, оно должно работать нормально.

0 голосов
/ 04 ноября 2019

Попробуйте удалить все свои dbms_output строки и перепроверить результат. Я предполагаю, что вы просто поместили очень длинный вывод в буфер. Также, если вам нужно загрузить одноразовый CSV-файл в Oracle Database, обратите внимание на утилиту sqlldr (например, https://www.orafaq.com/wiki/SQL*Loader_FAQ,). Он делает всю работу за вас, вы просто создаете целевую таблицу и выполняете некоторые настройки.

0 голосов
/ 03 ноября 2019

Я не знаю эту систему БД, но похоже, что эта строка:

v_Review  := REGEXP_SUBSTR(V_LINE, '[^,]+', 1, 5);

создает проблемы, пытаясь назначить слишком длинную строку для ограничения 2000 v_Review,Возможно, использование SUBSTR для сбора только первых 2000 символов этой строки может работать?

v_Review  := SUBSTR( REGEXP_SUBSTR(V_LINE, '[^,]+', 1, 5), 0, 2000 ); // maybe?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...