sql >> Databáze >  >> RDS >> Oracle

EXPORTOVAT JAKO VLOŽIT VÝKAZY:Ale v SQL Plus řádek přepíše 2500 znaků!

Páni, ta omezení jsou docela omezující, ale myslím, že to může být způsob, jak to obejít. Myslím, že na to možná budete muset napsat svůj vlastní malý skript.

Sám bych použil Javu s JDBC (ale bude stačit jakýkoli jazyk, který se může připojit a číst databázi a výstupní řetězce), napsat malý program, který načte sadu záznamů každého řádku v databázi. Potom pro každý z těchto řádků:

  • Vytvořte příkaz insert s úplnými daty. Pokud je to méně než 2 000 bajtů, pak to jednoduše vypište do souboru a přejděte na další řádek.

  • Jinak vytvořte příkaz insert pro každé pole, ale ponechte c13 pole jako '' (prázdné).

  • Pak, pokud váš c13input řetězec je delší než 2000 znaků, vytiskněte aktualizační příkaz ve tvaru "update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..." (přidáním dalších 2000 znaků) a poté proveďte c13input = c13input.substring(2000) k odstranění těchto znaků z vašeho řetězce.

  • Jednou c13input je kratší nebo rovna 2000 znakům, stačí odeslat jednu konečnou aktualizaci, která ji připevní na konec.

To vám umožní udržovat vaše jednotlivé příkazy SQL kolem značky 2000 znaků a efektivně provádět správné SQL pro opětovné naplnění další databázové tabulky.

Toto je typ věci, o které mluvím (pro tabulku obsahující pouze primární klíč c1 a velký houkající 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

Je zřejmé, že možná budete muset morfovat řetězce, aby bylo možné vkládat speciální znaky – nejsem si jistý, v jakém formátu je Oracle očekává, ale doufejme, že by to byla jednoduchá záležitost předání řetězců (r.get("c13") pokud je délka úplné vložky menší než 2000, f.substring(0,2000) a f pokud také vytváříte aktualizace) na pomocnou funkci.

Pokud je pravděpodobné, že toto morfování zvětší velikost vytištěného řádku, možná budete chtít snížit práh zpět na 1000, abyste byli v bezpečí, abyste zajistili, že morfovaný řetězec nebude mít za následek řádek větší než limit PL/SQL.

Omlouváme se, pokud se to zdá zamotané, ale omezení, která jste uvedl, nás trochu ochromují. Možná existuje lepší způsob, ale nenapadá mě žádný, který by vyhovoval všem vaše kritéria.

Aktualizace: Zdá se, že jste ještě více ochromený, než se původně myslelo:pokud se musíte omezit na SQL pro generování skript stejně jako jeho spuštění existuje způsob, i když je mučivý.

SQL můžete použít ke generování SQL. Pomocí mé výše uvedené tabulky s c1 a c13 , můžete:

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

To vám poskytne všechny vaše základní insert příkazy pro duplikování všeho kromě c13 sloupec.

Co pak musíte udělat, je vygenerovat více příkazů pro nastavení c13 . Chcete-li aktualizovat c13 pro všechny hodnoty délky 1000 nebo méně (jednoduchá sada):

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

Poté proveďte update c13 pro všechny hodnoty mezi 1001 a 2000 znaky (nastavit a přidat):

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.

A tak dále pro ty, které jsou dlouhé 2001 až 3000 a 3001 až 4000.

Pravděpodobně bude potřeba provést nějaké úpravy. Rád vám poradím, jak to vyřešit, ale moje touha dopracovat se na takové zrůdnosti až do konce je přinejlepším minimální :-)

Splní to práci? Ano. je to hezké? Řekl bych, že to bylo hlasité "NE!" ale vzhledem k vašim omezením to může být to nejlepší, v co můžete doufat.

Jako důkaz konceptu je zde SQL skript v DB2 (bez speciálních funkcí, měl by fungovat dobře v jakémkoli DBMS, který má length a substr ekvivalent):

# 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 tím se vygenerují následující řádky:

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

Rozdělením výstupních řádků dostaneme:

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ž by vám mělo poskytnout původní řady, i když kruhovým objezdem.

A to je asi tolik úsilí, kolik dokážu vynaložit na jednu otázku, aniž by se mi smažil mozek, takže se s vámi loučím, pokud mě neupozorní na nějaké závažné chyby.

Hodně štěstí s vaším projektem a přání všeho nejlepšího.



  1. Převeďte varchar na datetime v SQL Server

  2. Úvod do PostgreSQL

  3. Aktivní relace a stav SQL serveru

  4. Přidejte klauzule WHERE do SQL dynamicky / programově