我必须将Oracle表导出为INSERT STATEMENTS.
但是生成的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)
);
Run Code Online (Sandbox Code Playgroud)
假设:
a)我有义务将表数据导出为INSERT STATEMENTS; 我被允许使用UPDATE语句,以避免SQL*Plus错误"sp2-0027输入太长(> 2499个字符)";
b)我有义务使用SQL*Plus来执行如此生成的脚本.
c)请假设每条记录都包含特殊字符:CHR(10),CHR(13)等;
d)我不能使用SQL Loader;
e)我无法导出然后导入表:我只能通过SQL Plus使用INSERT/UPDATE语句添加"delta".
哇,这些限制是非常有限的,但我认为可能有办法绕过它.我想你可能必须为此编写自己的小脚本.
我自己会使用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
Run Code Online (Sandbox Code Playgroud)
显然,您可能需要变换字符串以允许插入特殊字符 - 我不确定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]","");
Run Code Online (Sandbox Code Playgroud)
这将为您提供所有基线insert语句,用于复制除c13列之外的所有内容.
您需要做的是生成更多用于设置的语句c13.要更新c13长度为1000或更小的所有值(简单集):
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
Run Code Online (Sandbox Code Playgroud)
然后,到updatec13为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.
Run Code Online (Sandbox Code Playgroud)
对于那些长度为2001到3000和3001到4000的那些等等.
可能需要进行一些调整.我很高兴为您提供一种解决方案,但是我希望能够完成这样一个怪物直到完成的愿望充其量:-)
它会完成工作吗?是.它漂亮吗?我会说这是一个响亮的"不!" 但是,考虑到你的限制,这可能是你所希望的最好的.
作为概念验证,这里是在DB2 SQL脚本(无特殊功能,虽然,它应该具有任何DBMS做工精细length和substr等效):
# 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;
Run Code Online (Sandbox Code Playgroud)
这会生成以下行:
> 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';
Run Code Online (Sandbox Code Playgroud)
打破输出线,我们得到:
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';
Run Code Online (Sandbox Code Playgroud)
它应该给你原始的行,虽然是以迂回的方式.
这就是我可以在没有大脑煎炸的情况下投入任何一个问题的努力,所以除非向我指出任何严重错误,否则我会向你提出申请.
祝你的项目好运,祝福你.
| 归档时间: |
|
| 查看次数: |
17571 次 |
| 最近记录: |