sql >> Database teknologi >  >> RDS >> Oracle

EKSPORTER SOM INDSÆT UDTALELSER:Men i SQL Plus tilsidesætter linjen 2500 tegn!

Wow, disse begrænsninger er ret begrænsende, men jeg tror, ​​der kan være en vej udenom. Jeg tænker, at du godt kan blive nødt til at skrive dit eget lille manuskript til dette.

Jeg ville selv bruge Java med JDBC (men ethvert sprog, der kan oprette forbindelse til og læse databasen, og output-strenge, vil gøre det), og skrive et lille program, som hentede et rekordsæt af hver række i databasen. Derefter for hver af disse rækker:

  • Konstruer en indsæt-sætning med de fulde data. Hvis dette er mindre end 2.000 bytes, skal du blot udskrive det til filen og gå videre til næste række.

  • Ellers opret en insert-sætning for hvert felt, men lad c13 være felt som '' (tom).

  • Så længe din c13input streng er større end 2000 tegn, udlæs en opdateringssætning på formen "update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..." (tilføje de næste 2000 tegn) og derefter c13input = c13input.substring(2000) for at fjerne disse tegn fra din streng.

  • En gang c13input er mindre end eller lig med 2000 tegn i længden, skal du blot udskrive en sidste opdatering for at slå den til sidst.

Dette giver dig mulighed for at holde dine individuelle SQL-sætninger omkring 2000-tegnsmærket og effektivt udføre den korrekte SQL for at genudfylde en anden databasetabel.

Det er den type ting, jeg taler om (for en tabel, der kun indeholder en primærnøgle c1 og en stor 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

Det er klart, at du muligvis skal omforme strengene for at tillade indsættelser af specialtegn - jeg er ikke sikker på, hvilket format Oracle forventer disse i, men det ville forhåbentlig være et simpelt spørgsmål om at sende strengene (r.get("c13") hvis længden af ​​den fulde indsættelse er mindre end 2000, f.substring(0,2000) og f hvis du også konstruerer opdateringer) til en hjælpefunktion for at gøre dette.

Hvis denne morphing sandsynligvis vil øge størrelsen af ​​den udskrevne linje, kan du for at være sikker sænke tærsklen til 1000 for at sikre, at den morphed streng ikke resulterer i en linje større end PL/SQL-grænsen.

Beklager, hvis det virker indviklet, men de begrænsninger, du har angivet, sætter os lidt i bund. Der er muligvis en bedre måde, men jeg kan ikke komme i tanke om en, der opfylder alle dine kriterier.

Opdatering: Det ser ud til, at du er endnu flere hæmmet end først antaget:hvis du skal begrænse dig til SQL for at generere scriptet såvel som at køre det, er der en måde, selv om det er pinligt.

Du kan bruge SQL til at generere SQL. Brug af min førnævnte tabel med c1 og c13 , kan du gøre:

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

Det vil give dig hele din basislinje insert sætninger til at duplikere alt undtagen c13 kolonne.

Hvad du så skal gøre er at generere flere sætninger for at indstille c13 . For at opdatere c13 for alle værdier med længde 1000 eller mindre (simpelt sæt):

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

Derefter for at update c13 for alle værdier mellem 1001 og 2000 tegn (indstil og tilføj):

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.

Og så videre for dem, der er 2001 til 3000 og 3001 til 4000 i længden.

Der skal sandsynligvis foretages nogle justeringer. Jeg er glad for at kunne give dig en måde at løse det på, men mit ønske om at arbejde på sådan en monstrøsitet til afslutning er i bedste fald minimal :-)

Vil det få arbejdet gjort? Ja. Er det smukt? Jeg vil sige, at det var et rungende "NEJ!" men givet dine begrænsninger er det måske det bedste du kan håbe på.

Som et bevis på konceptet er her et SQL-script i DB2 (ingen specielle funktioner dog, det burde fungere fint i enhver DBMS, der har en length og substr tilsvarende):

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

og dette genererer følgende linjer:

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

Ved at bryde udgangslinjerne ud får vi:

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

som skulle give dig de originale rækker, dog på en rundkørsel.

Og det er omtrent lige så mange kræfter, som jeg kan lægge i ethvert spørgsmål, uden at min hjerne steger, så jeg vil sige farvel, medmindre nogen alvorlige fejl bliver påpeget for mig.

Held og lykke med dit projekt, og de bedste ønsker.



  1. PostgreSQL JDBC-nulstreng taget som en bytea

  2. Er der noget som en zip() funktion i PostgreSQL, der kombinerer to arrays?

  3. Ændring af Django-udviklingsdatabase fra standard SQLite til PostgreSQL

  4. SET NULL:Angiv en streng, der skal returneres, når der forekommer en nulværdi i SQLcl / SQL*Plus