ЭКСПОРТ КАК ВСТАВИТЬ ЗАЯВЛЕНИЯ: Но в SQL Plus строка переопределяет 2500 символов! - PullRequest
7 голосов
/ 29 апреля 2010

Я должен экспортировать таблицу Oracle как INSERT STATEMENTS.

Но сгенерированные таким образом ВСТАВКИ ЗАЯВЛЕНИЯ переопределяют 2500 символов.

Я обязан выполнить их в SQL Plus, поэтому я получаю сообщение об ошибке.

Это моя таблица Oracle:

CREATE TABLE SAMPLE_TABLE
(
   C01   VARCHAR2 (5 BYTE) NOT NULL,
   C02   NUMBER (10) NOT NULL,
   C03   NUMBER (5) NOT NULL,
   C04   NUMBER (5) NOT NULL,
   C05   VARCHAR2 (20 BYTE) NOT NULL,
   c06   VARCHAR2 (200 BYTE) NOT NULL,
   c07   VARCHAR2 (200 BYTE) NOT NULL,
   c08   NUMBER (5) NOT NULL,
   c09   NUMBER (10) NOT NULL,
   c10   VARCHAR2 (80 BYTE),
   c11   VARCHAR2 (200 BYTE),
   c12   VARCHAR2 (200 BYTE),
   c13   VARCHAR2 (4000 BYTE),
   c14   VARCHAR2 (1 BYTE) DEFAULT 'N' NOT NULL,
   c15   CHAR (1 BYTE),
   c16   CHAR (1 BYTE)
);

Предположения:

а) Я ОБЯЗАН экспортировать данные таблиц как ВСТАВКИ ЗАЯВЛЕНИЙ; Мне разрешено использовать операторы UPDATE, чтобы избежать ошибки SQL * Plus "ввод sp2-0027 слишком длинный (> 2499 символов)";

b) Я ОБЯЗАН использовать SQL * Plus для выполнения сгенерированного сценария.

в) Предположим, что каждая запись может содержать специальные символы: CHR (10), CHR (13) и т. Д .;

d) Я не могу использовать загрузчик SQL;

e) Я НЕ МОГУ экспортировать, а затем импортировать таблицу: я могу только добавить «дельту», используя операторы INSERT / UPDATE через SQL Plus.

Ответы [ 2 ]

6 голосов
/ 13 мая 2010

Ух ты, эти ограничения довольно ограничивающие, но я думаю, что есть способ обойти это. Я думаю, вам, возможно, придется написать свой собственный маленький сценарий для этого.

Я бы сам использовал Java с JDBC (но подойдет любой язык, который может подключаться и читать базу данных и выводить строки), написав небольшую программу, которая извлекает набор записей для каждой строки в базе данных. Затем для каждой из этих строк:

  • Построить оператор вставки с полными данными. Если это меньше 2000 байт, просто выведите его в файл и перейдите к следующей строке.

  • В противном случае создайте оператор вставки для каждого поля, но оставьте поле c13 как '' (пусто).

  • Затем, если длина строки c13input превышает 2000 символов, выведите оператор обновления в форме "update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..." (добавляя следующие 2000 символов), а затем выполните c13input = c13input.substring(2000), чтобы удалить эти символы из вашей строки.

  • Если длина c13input меньше или равна 2000 символов, просто выведите одно окончательное обновление, чтобы прикрепить его к концу.

Это позволяет вам поддерживать индивидуальные операторы SQL в пределах 2000-символьной отметки и эффективно выполнять правильный SQL-запрос для повторного заполнения другой таблицы базы данных.

Я говорю об этом типе (для таблицы, содержащей только первичный ключ c1 и большой honkin 'varchar c13):

rowset r = db.exec ("select * from oldtable");
while r.next != NO_MORE_ROWS:
    string s = "insert into newtable (c1,c13) values ('" +
        r.get("c1") + "','" + r.get("c13") + "')"
    if s.len() < 2000:
        print s
    else:
        s = "insert into newtable (c1,c13) values ('" + r.get("c1") + "','')"
        print s
        f = r.get("c13")
        while f.len() > 2000:
            s = "update newtable set c13 = c13 || '" + f.substring(0,2000) + ')"
            f = f.substring(2000)
            print s
        endwhile
        s = "update newtable set c13 = c13 || '" + f + ')"
        print s
    endif
endwhile

Очевидно, что вам может понадобиться изменить строки, чтобы разрешить вставку специальных символов - я не уверен, в каком формате Oracle ожидает их, но, надеюсь, будет просто передать строки (r.get("c13"), если длина полной вставки меньше, чем 2000, f.substring(0,2000) и f, если вы также создаете обновления) для вспомогательной функции, которая делает это.

Если это изменение может увеличить размер напечатанной строки, вы можете снизить порог до 1000, чтобы быть безопасным, чтобы убедиться, что измененная строка не приводит к строке, превышающей предел PL / SQL .

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


Обновление: Похоже, вы даже больше подколены, чем первоначально предполагалось: если вам нужно ограничить себя SQL для генерации сценария, а также запустить его, есть способ, хотя и мучительный.

Вы можете использовать SQL для генерации SQL. Используя мою вышеупомянутую таблицу с c1 и c13, вы можете сделать:

select
    'insert into newtable (c1,c13) values ("' ||
    c1 ||
    '","");'
from oldtable;
# Xlates to: insert into newtable (c1,c13) values ("[c1]","");

Это даст вам все ваши базовые insert утверждения для дублирования всего, кроме столбца c13.

Затем вам нужно сгенерировать больше операторов для установки c13. Чтобы обновить c13 для всех значений длины 1000 или меньше (простой набор):

select
    'update newtable set c13 = "' ||
    c13 ||
    '" where c1 = "' ||
    c1 ||
    '";'
from oldtable where length(c13) <= 1000;
# Xlates to: update newtable set c13 = "[c13]" where c1 = "[c1]";
#   but only for rows where length([c13]) <= 1000

Затем до update c13 для всех значений от 1001 до 2000 символов (установите и добавьте):

select
    'update newtable set c13 = "' ||
    substring(c13,1,1000) ||
    '" where c1 = "' ||
    c1 ||
    '";'
from oldtable where length(c13) > 1000 and length(c13) <= 2000;
select
    'update newtable set c13 = c13 || "' ||
    substring(c13,1001,1000) ||
    '" where c1 = "' ||
    c1 ||
    '";'
from oldtable where length(c13) > 1000 and length(c13) <= 2000;
# Xlates to: update newtable set c13 =        "[c13a]" where c1 = "[c1]";
#            update newtable set c13 = c13 || "[c13b]" where c1 = "[c1]";
#   but only for rows where length([c13]) > 1000 and <= 2000
#   and [c13a]/[c13b] are the first/second thousand chars of c13.

И так далее для тех, которые имеют длину от 2001 до 3000 и от 3001 до 4000.

Скорее всего, потребуется некоторая настройка. Я рад дать вам способ ее решить, но мое желание работать над таким чудовищем до самого завершения в лучшем случае минимально: -)

Это выполнит работу? Да. Это красиво? Я бы сказал, что это было громкое "НЕТ!" но, учитывая ваши ограничения, это может быть лучшим, на что вы можете надеяться.


В качестве подтверждения концепции приведем сценарий SQL в DB2 (однако никаких специальных функций он не должен работать в любой СУБД, эквивалентной length и substr):

# Create table and populate.

DROP TABLE XYZ;
COMMIT;
CREATE TABLE XYZ (F1 VARCHAR(1),F2 VARCHAR(20));
COMMIT;
INSERT INTO XYZ VALUES ('1','PAX');
INSERT INTO XYZ VALUES ('2','GEORGE');
INSERT INTO XYZ VALUES ('3','VLADIMIR');
INSERT INTO XYZ VALUES ('4','ALEXANDRETTA');
SELECT * FROM XYZ ORDER BY F1;

# Create initial insert statem,ents.

SELECT 'INSERT INTO XYZ (F1,F2) VALUES (' || F1 ','''');' 
    FROM XYZ;

# Updates for 1-5 character F2 fields.

SELECT 'UPDATE XYZ SET F2 = ''' || F2 ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) <= 5;

# Updates for 6-10 character F2 fields.

SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;

SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6) ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;

# Updates for 11-15 character F2 fields.

SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;

SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6,5) ||
    ''' WHERE F1 = ''' || F1 || ''';'
  FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;

SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,11) || 
    ''' WHERE F1 = ''' || F1 || ''';'
    FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;

и это генерирует следующие строки:

> DROP TABLE XYZ;
> COMMIT;
> CREATE TABLE XYZ (F1 VARCHAR(1),F2 VARCHAR(20));
> COMMIT;
> INSERT INTO XYZ VALUES ('1','PAX');
> INSERT INTO XYZ VALUES ('2','GEORGE');
> INSERT INTO XYZ VALUES ('3','VLADIMIR');
> INSERT INTO XYZ VALUES ('4','ALEXANDRETTA');
> SELECT * FROM XYZ;
    F1  F2
    --  ------------
    1   PAX
    2   GEORGE
    3   VLADIMIR
    4   ALEXANDRETTA

> SELECT 'INSERT INTO XYZ (F1,F2) VALUES (' || F1 || ','''');'
> FROM XYZ;
    INSERT INTO XYZ (F1,F2) VALUES (1,'');
    INSERT INTO XYZ (F1,F2) VALUES (2,'');
    INSERT INTO XYZ (F1,F2) VALUES (3,'');
    INSERT INTO XYZ (F1,F2) VALUES (4,'');

> SELECT 'UPDATE XYZ SET F2 = ''' || F2 ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) <= 5;
    UPDATE XYZ SET F2 = 'PAX' WHERE F1 = '1';

> SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;
    UPDATE XYZ SET F2 = 'GEORG' WHERE F1 = '2';
    UPDATE XYZ SET F2 = 'VLADI' WHERE F1 = '3';

> SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 5 AND LENGTH(F2) <= 10;
    UPDATE XYZ SET F2 = F2 || 'E' WHERE F1 = '2';
    UPDATE XYZ SET F2 = F2 || 'MIR' WHERE F1 = '3';

> SELECT 'UPDATE XYZ SET F2 = ''' || SUBSTR(F2,1,5) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;
    UPDATE XYZ SET F2 = 'ALEXA' WHERE F1 = '4';

> SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,6,5) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;
    UPDATE XYZ SET F2 = F2 || 'NDRET' WHERE F1 = '4';

> SELECT 'UPDATE XYZ SET F2 = F2 || ''' || SUBSTR(F2,11) ||
> ''' WHERE F1 = ''' || F1 || ''';'
> FROM XYZ WHERE LENGTH(F2) > 10 AND LENGTH(F2) <= 15;
    UPDATE XYZ SET F2 = F2 || 'TA' WHERE F1 = '4';

Разбивая выходные строки, мы получаем:

INSERT INTO XYZ (F1,F2) VALUES (1,'');
INSERT INTO XYZ (F1,F2) VALUES (2,'');
INSERT INTO XYZ (F1,F2) VALUES (3,'');
INSERT INTO XYZ (F1,F2) VALUES (4,'');
UPDATE XYZ SET F2 = 'PAX' WHERE F1 = '1';
UPDATE XYZ SET F2 = 'GEORG' WHERE F1 = '2';
UPDATE XYZ SET F2 = 'VLADI' WHERE F1 = '3';
UPDATE XYZ SET F2 = F2 || 'E' WHERE F1 = '2';
UPDATE XYZ SET F2 = F2 || 'MIR' WHERE F1 = '3';
UPDATE XYZ SET F2 = 'ALEXA' WHERE F1 = '4';
UPDATE XYZ SET F2 = F2 || 'NDRET' WHERE F1 = '4';
UPDATE XYZ SET F2 = F2 || 'TA' WHERE F1 = '4';

, который должен дать вам исходные строки, хотя и окольным путем.


И это примерно столько же усилий, сколько я могу поставить на любой вопрос, не напрягая мозги, поэтому я попрошу вас, если на меня не укажут какие-либо серьезные ошибки.

Удачи в вашем проекте и наилучших пожеланий.

1 голос
/ 30 апреля 2010

Вы можете использовать инструмент Jailer (http://jailer.sf.net), чтобы экспортировать данные таблицы как ВСТАВКИ.

...