Oracle
 sql >> Baza danych >  >> RDS >> Oracle

EXPORT AS INSERT STATEMENTS:Ale w SQL Plus linia zastępuje 2500 znaków!

Wow, te ograniczenia są dość ograniczające, ale myślę, że można to obejść. Myślę, że być może będziesz musiał napisać w tym celu swój własny mały skrypt.

Sam bym używał Javy z JDBC (ale każdy język, który może łączyć się z bazą danych i odczytywać ją, a także łańcuchy wyjściowe, wystarczy), pisząc mały program, który pobierał zestaw rekordów z każdego wiersza w bazie danych. Następnie dla każdego z tych wierszy:

  • Skonstruuj instrukcję INSERT z pełnymi danymi. Jeśli jest to mniej niż 2000 bajtów, po prostu wyślij go do pliku i przejdź do następnego wiersza.

  • W przeciwnym razie utwórz instrukcję INSERT dla każdego pola, ale pozostaw c13 pole jako '' (pusty).

  • Następnie, o ile Twój c13input ciąg jest większy niż 2000 znaków, wyślij instrukcję aktualizacji w postaci "update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..." (dołączając następne 2000 znaków), a następnie wykonaj c13input = c13input.substring(2000) aby usunąć te znaki z ciągu.

  • Raz c13input ma długość mniejszą lub równą 2000 znaków, po prostu wyślij jedną ostateczną aktualizację, aby dołączyć ją na końcu.

Pozwala to na utrzymanie indywidualnych instrukcji SQL wokół znaku 2000 znaków i efektywne wykonanie poprawnego kodu SQL w celu ponownego zapełnienia innej tabeli bazy danych.

To jest rodzaj rzeczy o których mówię (dla tabeli zawierającej tylko klucz podstawowy c1 i wielki 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

Oczywiście może być konieczne przekształcenie ciągów, aby umożliwić wstawianie znaków specjalnych — nie jestem pewien, w jakim formacie oczekuje ich Oracle, ale mam nadzieję, że będzie to prosta sprawa przekazania ciągów (r.get("c13") jeśli długość pełnej wstawki jest mniejsza niż 2000, f.substring(0,2000) i f jeśli tworzysz również aktualizacje) do funkcji pomocniczej, aby to zrobić.

Jeśli ta morfing prawdopodobnie zwiększy rozmiar drukowanej linii, możesz chcieć obniżyć próg z powrotem do 1000, aby być bezpiecznym, aby upewnić się, że przekształcony łańcuch nie spowoduje powstania linii większej niż limit PL/SQL.

Przepraszam, jeśli wydaje się to zawiłe, ale ograniczenia, które określiłeś, trochę nas osłabiają. Być może istnieje lepszy sposób, ale nie przychodzi mi do głowy taki, który spełnia wszystkie Twoje kryteria.

Aktualizacja: Wygląda na to, że jesteś jeszcze więcej hamowane, niż początkowo sądzono:jeśli musisz ograniczyć się do SQL do generowania zarówno skrypt, jak i jego uruchamianie, jest sposób, choć jest torturą.

Możesz użyć SQL do wygenerowania SQL. Używanie mojej wyżej wymienionej tabeli z c1 i c13 , możesz zrobić:

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

To da ci całą swoją bazę insert instrukcje do powielania wszystkiego oprócz c13 kolumna.

Następnie musisz wygenerować więcej instrukcji do ustawienia c13 . Aby zaktualizować c13 dla wszystkich wartości długości 1000 lub mniejszych (zestaw prosty):

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

Następnie, aby update c13 dla wszystkich wartości od 1001 do 2000 znaków (ustaw, a następnie dołącz):

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.

I tak dalej dla tych, które mają długość od 2001 do 3000 i od 3001 do 4000.

Prawdopodobnie trzeba będzie dokonać pewnych poprawek. Cieszę się, że mogę dać Ci sposób na rozwiązanie tego problemu, ale moje pragnienie pracy nad taką potwornością do końca jest w najlepszym razie minimalne :-)

Czy to wykona zadanie? Tak. Czy to jest ładne? Powiedziałbym, że było to głośne „NIE!” ale biorąc pod uwagę twoje ograniczenia, może to być najlepsze, na co możesz liczyć.

Jako dowód koncepcji, oto skrypt SQL w DB2 (choć bez specjalnych funkcji, powinien działać dobrze w każdym DBMS, który ma length i substr odpowiednik):

# 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;

a to generuje następujące linie:

> 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';

Przełamując linie wyjściowe, otrzymujemy:

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';

co powinno dać oryginalne wiersze, aczkolwiek w sposób okrężny.

I to jest mniej więcej tyle wysiłku, ile mogę włożyć w jedno pytanie bez męczenia mojego mózgu, więc pożegnam się, chyba że wskażę mi jakieś poważne błędy.

Powodzenia w Twoim projekcie i wszystkiego najlepszego.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak zwrócić listę obsługiwanych terytoriów w Oracle?

  2. Jak zdalnie połączyć się z bazą danych Oracle 11g?

  3. Oracle JDBC i typ danych Oracle CHAR

  4. Oracle Insert Select z zamówieniem według

  5. Dowiedz się, jak wykonać procedurę w Toad For Oracle