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ďtec13input = 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.