sql >> Database >  >> RDS >> Oracle

EXPORTEREN ALS INSERT-VERKLARINGEN:Maar in SQL Plus overschrijft de regel 2500 tekens!

Wow, die beperkingen zijn behoorlijk beperkend, maar ik denk dat er een manier omheen kan zijn. Ik denk dat je hiervoor misschien je eigen kleine script moet schrijven.

Ik zou Java zelf met JDBC gebruiken (maar elke taal die verbinding kan maken met de database en deze kan lezen, en strings kan uitvoeren, is voldoende), door een klein programma te schrijven dat een recordset van elke rij in de database ophaalde. Dan, voor elk van die rijen:

  • Maak een insert-statement met de volledige gegevens. Als dit minder is dan 2.000 bytes, voer het dan gewoon uit naar het bestand en ga verder naar de volgende rij.

  • Maak anders een insert-statement voor elk veld, maar laat de c13 veld als '' (leeg).

  • Dan, zolang uw c13input string groter is dan 2000 tekens, voer dan een update-instructie uit van de vorm "update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..." (voeg de volgende 2000 tekens toe) en voer vervolgens c13input = c13input.substring(2000) uit om die tekens uit je string te verwijderen.

  • Eenmaal c13input is minder dan of gelijk aan 2000 karakters lang, voer gewoon een laatste update uit om het aan het einde te tackelen.

Hierdoor kunt u uw individuele SQL-instructies rond de 2000-tekens houden en efficiënt de juiste SQL uitvoeren om een ​​andere databasetabel opnieuw te vullen.

Dit is het soort dingen waar ik het over heb (voor een tabel die alleen een primaire sleutel bevat c1 en een grote 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

Het is duidelijk dat je de tekenreeksen moet morphen om invoegingen van speciale tekens toe te staan ​​- ik weet niet zeker in welk formaat Oracle deze verwacht, maar het zou hopelijk een kwestie zijn van het doorgeven van de tekenreeksen (r.get("c13") als de lengte van de volledige invoeging kleiner is dan 2000, f.substring(0,2000) en f als je ook updates aan het maken bent) naar een helperfunctie om dit te doen.

Als die morphing waarschijnlijk de grootte van de afgedrukte regel vergroot, kunt u voor de zekerheid de drempel terugbrengen naar 1000, om ervoor te zorgen dat de morphed-tekenreeks niet resulteert in een regel die groter is dan de PL/SQL-limiet.

Sorry als dat ingewikkeld lijkt, maar de beperkingen die je hebt gesteld verlammen ons een beetje. Er is misschien een betere manier, maar ik kan er geen bedenken die aan alles voldoet uw criteria.

Bijwerken: Het lijkt erop dat je zelfs meer bent verlamd dan oorspronkelijk gedacht:als je je moet beperken tot SQL voor genereren zowel het script als het uitvoeren ervan, is er een manier, hoe martelend die ook is.

U kunt SQL gebruiken om SQL te genereren. Mijn bovengenoemde tabel gebruiken met c1 en c13 , je kunt het volgende doen:

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

Dat geeft je al je baseline insert instructies voor het dupliceren van alles behalve de c13 kolom.

Wat u dan moet doen, is meer instructies genereren voor het instellen van c13 . c13 updaten voor alle waarden met een lengte van 1000 of minder (eenvoudige set):

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

Om vervolgens te update c13 voor alle waarden tussen 1001 en 2000 tekens (stel in en voeg toe):

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.

En zo verder voor degenen die 2001-to-3000 en 3001-to-4000 lang zijn.

Er zal waarschijnlijk wat moeten worden aangepast. Ik geef je graag een manier om het op te lossen, maar mijn verlangen om aan zo'n gedrocht te werken tot het voltooid is, is op zijn best minimaal :-)

Zal het de klus klaren? Ja. Is het mooi? Ik zou zeggen dat het een volmondig "NEE!" was. maar gezien je beperkingen is dat misschien wel het beste waar je op kunt hopen.

Als proof of concept is hier een SQL-script in DB2 (geen speciale functies, het zou prima moeten werken in elk DBMS met een length en substr equivalent):

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

en dit genereert de volgende regels:

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

Als we de uitvoerlijnen uitbreken, krijgen we:

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

die je de originele rijen zou moeten geven, zij het via een omweg.

En dat is ongeveer net zoveel moeite als ik in een vraag kan steken zonder dat mijn hersens frituren, dus ik zeg u adieu tenzij mij op ernstige fouten wordt gewezen.

Veel succes met je project en de beste wensen.



  1. Kleur en lettertypen wijzigen in SQL Server Management Studio (SSMS) - SQL Server / TSQL-zelfstudie, deel 12

  2. Maak een gekoppelde server tussen twee Docker-containers met SQL Server (T-SQL-voorbeeld)

  3. Een DBF-bestand importeren in SQL Server

  4. Hoe een afbeeldingsveld naar een bestand te exporteren?