ROWNUM работает только для одной строки. Как получить строки после этого?

Я хочу извлечь данные BLOB и записать из них файл (предполагаю, что это должен быть excel, txt или любой другой). В одной ячейке может быть до 60 тыс. символов. Я хотел написать скрипт, который считывает всю таблицу с данными BLOB и записывает их в файл. В приведенном ниже коде ROWNUM работает только для одной строки. какая альтернатива? Или есть другой скрипт, который может помочь мне достичь моей конечной цели - прочитать BLOB и записать файл?

SET SERVEROUTPUT ON;
    DECLARE
       TotalRows NUMBER;
       TotalChar NUMBER;
       CharCounter NUMBER;
    BEGIN
    SELECT count(*) INTO TotalRows FROM <TableName>;
            --dbms_output.Put_line(RC);
            --END;
       FOR RC IN 1..TotalRows
       LOOP
           -----------------Code for Rows starts--------------------------------------------------------------------------------
            dbms_output.Put_line('Row '||RC||' Started.');
            SELECT Length(<ColumnWithBLOBDataType>) INTO TotalChar FROM <TableName> where **Rownum = RC**;
            dbms_output.Put_line('Crossed Char counting query. TotalChar='||TotalChar);
            CharCounter:=TotalChar/2000+1;
            dbms_output.Put_line('Loop will run these many times= '||CharCounter|| ' and Total Chars=' ||TotalChar);
            For CC IN 1..CharCounter
            LOOP
                dbms_output.Put_line('Trip: '||CC);
            END LOOP;  
        -----------------Code for Rows Ends----------------------------------------------------------------------------------------
            TotalChar :=0;
            dbms_output.Put_line('Row '|| RC||' Done. TotalChar='|| TotalChar);
       END LOOP;
       dbms_output.Put_line('Exited loop 1.');
    END;

person user7345601    schedule 02.07.2018    source источник
comment
записывает его в файл: вы хотите записать все большие двоичные объекты в один большой файл?   -  person wolφi    schedule 02.07.2018
comment
Данные BLOB — это в основном данные конфигурации приложения, которые я хочу прочитать и сравнить с той же конфигурацией после изменений, чтобы точно указать все внесенные изменения. Пожалуйста, предложите, есть ли лучший способ добиться этого. Я думал записать это в файл и сравнить с другим файлом, созданным после изменений. Спасибо!   -  person user7345601    schedule 04.07.2018
comment
Максимальное количество символов в ячейке, которое я видел, составляло 60 тыс. символов. И файл конфигурации, созданный приложением, имеет размер менее 50 МБ. Пожалуйста, предложите возможное / лучшее решение, учитывая, что я не эксперт в программировании, но могу немного кодировать в PL SQL, VB, .net и т. д.   -  person user7345601    schedule 04.07.2018
comment
Если это данные конфигурации, то CLOB может быть лучшим типом данных, чем BLOB, который предназначен для двоичных данных.   -  person wolφi    schedule 04.07.2018
comment
Лично я, вероятно, оставил бы данные в базе данных и сделал снимок состояния до: CREATE TABLE mybefore AS SELECT * FROM mytable. После изменения я бы сравнил таблицу mybefore и mytable, чтобы SQL мог определить, какие ячейки изменились...   -  person wolφi    schedule 04.07.2018
comment
Спасибо друг! Однако я думаю, что мы сможем найти, где это изменилось, но не то, что изменилось. В таблице 4 столбца и всего 23 строки. Столбец BLOB имеет от 22 тыс. до 60 тыс. шестнадцатеричных символов, и я предполагаю, что в одной ячейке содержится много объектов. Проблема в том, что мы не знаем о данных и их структуре. Есть ли способ сравнить две таблицы?   -  person user7345601    schedule 04.07.2018
comment
Да, см. этот вопрос. В идеале у вас должно быть какое-то diff сравнение, но я не знаю ни одного.   -  person wolφi    schedule 05.07.2018


Ответы (1)


Обычно вы не используете ROWNUM для выбора строк из таблицы. Это не безопасно и не нужно. Обычно вы можете сделать это с помощью одного цикла FOR SELECT:

DECLARE
   CharCounter NUMBER;
   part VARCHAR2(30000);
   offset NUMBER;
BEGIN
  FOR r IN (SELECT c,
                   rownum as rc,
                   dbms_lob.getlength(c) as totalchar
              FROM mytable)
  LOOP
    -----------------Code for Rows starts--------------------------------------------------------------------------------
    dbms_output.put_line('Row '||r.rc||' Started.');

    dbms_output.put_line('Crossed Char counting query. TotalChar='||r.totalchar);

    offset := 1;
    WHILE (offset <= r.totalchar) LOOP
      part := dbms_lob.substr(r.c, 20000, offset);
      offset := offset + length(part);      
      dbms_output.put(part);
    END LOOP;
    dbms_output.put_line('');

  END LOOP;
END;
/
person wolφi    schedule 02.07.2018
comment
Спасибо! Я попробую это и дам вам знать. - person user7345601; 04.07.2018
comment
Приятель, я попробовал это, он работает, т.е. он проходит через все строки, однако из-за буфера символьных строк выдает ошибку (ORA-06502: PL/SQL: ошибка числового значения или значения: буфер символьной строки слишком мал). - person user7345601; 04.07.2018
comment
Приятель, я пробовал это, он работает, т. Е. Он проходит через все строки, однако из-за буфера символьных строк выдает ошибку (ORA-06502: PL/SQL: ошибка числового значения или значения: буфер символьной строки слишком мал. ORA-06512: at строка 13 06502. 00000 - PL/SQL: числовая ошибка или ошибка значения%s). Если я уменьшу 20000 до 15000 в (part:= dbms_lob.substr(r.DATA, 20000, offset), он вернет 11 строк вместе с той же ошибкой. Кроме того, я пытался использовать utl_raw.cast_to_varchar2 с dbms_lob.substr(r. DATA, 20000, смещение) в r.DATA, то возникает та же ошибка, что и выше, с нулевыми строками. - person user7345601; 04.07.2018
comment
Это может быть проблема с многобайтовыми символами. Максимальная длина PL/SQL VARCHAR2 составляет 32767. Символ может иметь не более 4 байтов. Поэтому я бы попробовал с размером буфера 8000. - person wolφi; 04.07.2018
comment
И этот ответ показывает только, как читать данные из вашей таблицы. Это не очень хороший способ записи в один или несколько файлов... - person wolφi; 04.07.2018
comment
Спасибо, есть ли способ создать файл, пожалуйста? - person user7345601; 05.07.2018
comment
Это отдельный вопрос ;-) Это можно сделать с помощью UTL_FILE, но файл должен быть доступен с сервера базы данных. - person wolφi; 05.07.2018
comment
Добро пожаловать. Пожалуйста, взгляните на stackoverflow.com/help/someone-answers. - person wolφi; 06.07.2018