但是生成的INSERT语句覆盖2500个字符.
我不得不在sql Plus中执行它们,所以我收到一条错误消息.
这是我的Oracle表:
CREATE TABLE SAMPLE_TABLE ( C01 VARCHAR2 (5 BYTE) NOT NULL,C02 NUMBER (10) NOT NULL,C03 NUMBER (5) NOT NULL,C04 NUMBER (5) NOT NULL,C05 VARCHAR2 (20 BYTE) NOT NULL,c06 VARCHAR2 (200 BYTE) NOT NULL,c07 VARCHAR2 (200 BYTE) NOT NULL,c08 NUMBER (5) NOT NULL,c09 NUMBER (10) NOT NULL,c10 VARCHAR2 (80 BYTE),c11 VARCHAR2 (200 BYTE),c12 VARCHAR2 (200 BYTE),c13 VARCHAR2 (4000 BYTE),c14 VARCHAR2 (1 BYTE) DEFAULT 'N' NOT NULL,c15 CHAR (1 BYTE),c16 CHAR (1 BYTE) );
假设:
a)我有义务将表数据导出为INSERT STATEMENTS;我被允许使用UPDATE语句,以避免sql * Plus错误“sp2-0027输入太长(> 2499个字符)”;
c)请假设每条记录都包含特殊字符:CHR(10),CHR(13)等;
d)我不能使用sql Loader;
我自己会使用Java和JDBC(但是任何可以连接和读取数据库并输出字符串的语言都可以),编写一个程序来检索数据库中每一行的记录集.然后,对于这些行中的每一行:
>使用完整数据构造一个insert语句.如果这小于2,000字节,则只需将其输出到文件并继续下一行.
>否则为每个字段创建一个insert语句,但将c13字段保留为”(空).
>然后,只要您的c13input字符串大于2000个字符,就输出“update tbl set c13 = c13 ||’”c13input.substring(0,2000)“’where …”形式的更新语句(追加)接下来的2000个字符)然后执行c13input = c13input.substring(2000)来从字符串中去掉那些字符.
>一旦c13input长度小于或等于2000个字符,只需输出一个最终更新以在最后添加它.
这允许您将各个sql语句保持在2000个字符的标记周围,并有效地执行正确的sql以重新填充另一个数据库表.
这是我正在谈论的事情类型(对于只包含主键c1和大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
显然,您可能需要变换字符串以允许插入特殊字符 – 我不确定Oracle期望这些格式是什么格式,但希望传递字符串(r.get(“c13”)如果是一个简单的事情)完整插入的长度小于2000,f.substring(0,2000)和f,如果你正在构建更新)到辅助函数来执行此操作.
如果该变形可能会增加打印行的大小,您可能希望将阈值降回1000以确保安全,以确保变形字符串不会导致大于PL / sql限制的行.
很抱歉,如果这看起来很复杂,但你所说的限制会让我们陷入困境.可能有更好的方法,但我想不出符合所有标准的方法.
更新:看起来你比原先想象的更加困难:如果你必须限制自己使用sql来生成脚本以及运行脚本,那么有一种方法,虽然它是折磨的.
您可以使用sql生成sql.使用我上面提到的c1和c13表,您可以:
select 'insert into newtable (c1,c13) values ("' || c1 || '","");' from oldtable; # Xlates to: insert into newtable (c1,c13) values ("[c1]","");
这将为您提供所有基线插入语句,用于复制除c13列之外的所有内容.
您需要做的是生成更多用于设置c13的语句.要为长度为1000或更小的所有值(简单集)更新c13:
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
然后,更新c13以获取1001和2000个字符之间的所有值(设置然后追加):
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.
对于那些长度为2001到3000和3001到4000的那些等等.
可能需要进行一些调整.我很高兴为您提供一种解决方案,但是我希望能够完成这样一个怪物直到完成的愿望充其量:-)
它会完成工作吗?是.它漂亮吗?我会说这是一个响亮的“不!”但是,考虑到你的限制,这可能是你所希望的最好的.
作为一个概念证明,这里是DB2中的一个sql脚本(虽然没有特殊功能,但它应该可以在任何具有length和substr等效的DBMS中正常工作):
# 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,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,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;
这会生成以下行:
> 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,F2) VALUES (3,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,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,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,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';
打破输出线,我们得到:
INSERT INTO XYZ (F1,''); INSERT INTO XYZ (F1,''); 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';
它应该给你原始的行,虽然是以迂回的方式.
这就是我可以在没有大脑煎炸的情况下投入任何一个问题的努力,所以除非向我指出任何严重的错误,否则我会向你提出申请.
祝你的项目好运,祝福你.