EXPORT AS INSERT 语句:但是在 SQL Plus 中,该行覆盖了 2500 个字符!

2023-11-27

我必须将 Oracle 表导出为 INSERT 语句。

但这样生成的 INSERT STATEMENTS 会覆盖 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 语句;我可以使用 UPDATE 语句,以避免 SQL*Plus 错误“sp2-0027 输入太长(>2499 个字符)”;

b) 我必须使用 SQL*Plus 来执行如此生成的脚本。

c) 请假设每条记录都可以包含特殊字符:CHR(10)、CHR(13) 等;

d) 我不能使用 SQL Loader;

e) 我无法导出然后导入表:我只能通过 SQL Plus 使用 INSERT / UPDATE 语句添加“增量”。


哇,这些限制相当有限,但我认为可能有办法解决它。我认为您可能必须为此编写自己的小脚本。

我自己会使用 Java 和 JDBC(但任何可以连接并读取数据库并输出字符串的语言都可以),编写一个小程序来检索数据库中每一行的记录集。然后,对于每一行:

  • 使用完整数据构造一条插入语句。如果小于 2,000 字节,则只需将其输出到文件并移至下一行。

  • 否则为每个字段创建一条插入语句,但保留c13字段为''(空的)。

  • 那么,只要你的c13input字符串大于2000个字符,输出以下形式的更新语句"update tbl set c13 = c13 || '" + c13input.substring (0,2000) + "' where ..."(追加接下来的 2000 个字符)然后执行c13input = c13input.substring(2000)从字符串中删除这些字符。

  • Once c13input长度小于或等于 2000 个字符,只需输出一个最终更新以将其附加到末尾。

这使您可以将各个 SQL 语句保持在 2000 个字符左右,并有效地执行正确的 SQL 来重新填充另一个数据库表。

这就是我正在讨论的类型(对于仅包含主键的表c1和一个大喇叭 varcharc13):

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) and f如果您也在构建更新)到辅助函数来执行此操作。

如果该变形可能会增加打印行的大小,为了安全起见,您可能需要将阈值降回 1000,以确保变形后的字符串不会导致大于 PL/SQL 限制的行。

抱歉,如果这看起来很复杂,但您所说的限制对我们来说有点束缚。可能有更好的方法,但我想不出一个可以满足的方法all你的标准。


Update:看来你甚至more比最初想象的更糟糕:如果你必须将自己限制在 SQL 上生成脚本以及运行它,有一种方法,尽管它很痛苦。

您可以使用 SQL 来生成 SQL。使用我的上述表格c1 and c13, 你可以做:

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

这会给你所有的基线insert复制除以下内容之外的所有内容的语句c13 column.

然后你需要做的是生成更多的语句来设置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

然后,到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.

对于长度为 2001-to-3000 和 3001-to-4000 的,依此类推。

可能需要进行一些调整。我很高兴为您提供解决该问题的方法,但我对这样一个怪物的工作直至完成的愿望充其量是微乎其微的:-)

它能完成工作吗?是的。漂亮吗?我想说这是一个响亮的“不!”但是,考虑到您的限制,这可能是您所能期望的最好结果。


作为概念证明,这里有一个 DB2 中的 SQL 脚本(虽然没有特殊功能,但它应该可以在任何具有以下功能的 DBMS 中正常工作):length and 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;

这会生成以下几行:

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

分解输出线,我们得到:

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

这应该给你原始的行,尽管是以一种迂回的方式。


这就是我在不费脑子的情况下能对任何一个问题投入的最大努力,所以除非有人向我指出任何严重的错误,否则我会向你告别。

祝您的项目顺利,并致以最美好的祝愿。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EXPORT AS INSERT 语句:但是在 SQL Plus 中,该行覆盖了 2500 个字符! 的相关文章

随机推荐

  • 数组连接返回空数组

    我使用以下方法将多个项目添加到数组中concat在事件处理程序中如下 var selectedValues each selected levels data kendoListBox dataSource data function i
  • 如何以编程方式为 Java 中的 AWS Cognito 用户池中的已登录用户启用或禁用 MFA?

    我正在使用以下代码 但它不会更改 AWS 中的任何内容 尽管它不会返回文档中所述的任何内容 https docs aws amazon com cognito user identity pools latest APIReference
  • jQuery:删除除内部元素之外的元素

    有没有办法删除除内部元素之外的元素 div class gallery a href images rep png title rep img src http example com uploads rep png class thumb
  • 是否可以将预览、图像分析和视频捕获与 CameraX 结合起来?

    是否可以绑定Preview ImageAnalysis and VideoCapture同时 成对组合 所有可能的组合 即 Preview ImageAnalysis Preview VideoCapture and ImageAnalys
  • 如何从magento中的cms页面传递带有块表单内容的参数

    我想传递一个带有块代码的变量 例如magento中的JSON类型 block type multibanners multibanners category id 9 name multibanners alias multibanners
  • ContentResolver.insert 始终返回 null

    我试图通过按下按钮来设置自定义铃声 但从 ContentResolver 的插入方法中获取 null 以下是负责设置铃声的代码 我检查了 stackoverflow 本身 一些用户说它对他们有用 但在我的例子中 我将变量 newUri 设置
  • UserPrincipal 对象中的域名在哪里?

    我正在使用System DirectoryServices ActiveDirectory类来查找所有 Active Directory 用户 代码很简单 var context new PrincipalContext ContextTy
  • 使用 Firebase 进行分页/无限滚动

    我有一个我创建的节点的子节点childByAutoId 我正在尝试在 TableView 中使用它进行分页 但我不知道如何操作 我的数据库如下所示 items KKM7Fv8H7dCiD2xChYB userID 1231231 KKM7F
  • VBA 分割字符串循环

    我正在尝试拆分字符串并创建一个循环来遍历列中的单元格 存在一些挑战 拆分适用于ActiveCell only 循环遍历所有单元格直到 LastRow 但填充所有单元格 分割字符串值来自ActiveCell only 数组的分割开始于i 0即
  • HTML5 输入标记中的数字格式

    这是我的输入
  • ReactJS Array.push 函数在 setState 中不起作用

    到目前为止 我正在制作一个原始的测验应用程序 其中包含 3 个问题 全部是对还是错 在我的handleContinue方法有一个调用 将用户输入从无线电表单推送到userAnswers大批 第一次运行效果很好handleContinue 之
  • Gridview - 单击图像可在 Viewpager 中查看图像

    这是一个从 json 获取图像的 gridview 而且效果很好 我想单击此网格视图中的图像以显示完整图像并可以滑动它 我发现这个问题的解决方案是使用Viewpager 如何在gridview中点击图片来显示图片并且可以滑动 您可以更轻松地
  • 监听Mac键盘播放/暂停事件

    某些 Mac 应用程序 例如 iTunes 和 Spotify 会对某些 Apple 键盘上的播放 暂停 下一个 上一个按钮做出反应 想必他们正在利用某种 NSNotification 我该如何做同样的事情呢 我通过使用以下命令对 NSAp
  • 捆绑包有问题

    我尝试命令bundle install local但它显示问题 bash usr local bin bundle usr local bin ruby bad interpreter No such file or directory 请
  • \n 在 python 中的工作[重复]

    这个问题在这里已经有答案了 我目前正在学习 python 课程 当谈论转义序列时 他们谈到 n 用于在新行中打印字符串 但是当它以以下方式使用时为什么我会得到不同的输出 gt gt gt st Hello nWorld gt gt gt s
  • Python:os.path.isfile 无法识别以数字开头的文件

    所以 我正在尝试合并os path isfile or os path exists进入我的代码 在搜索以字母开头的文件名时成功找到某些常规文件 pdf png 我正在使用的文件命名标准 并且不能因用户而更改 以数字开头 随后无法使用相同的
  • 没有 main 方法的 C# 类

    我正在学习 C 而且对它很陌生 所以请原谅我提出这个看似愚蠢的问题 我有一些 Java 经验 我注意到 C 程序也需要一个main 他们的主类中的方法 如果我想创建一个不是主类的类 即导入到主类中的类 该怎么办 我尝试这样做 当我编译时 通
  • Node.js 的进程间和服务器间事件发射器/监听器?

    目前 我正在使用事件发射器2作为我的应用程序中的消息总线 我真的很喜欢它 不管怎样 现在我需要一个消息总线 它不仅可以在进程内工作 而且可以在进程间工作 我理想的候选人是 与 EventEmitter2 API 兼容 直接替代品 无需专用服
  • 无法使用有效的 Sectigo 代码签名证书对 VBA 进行签名

    我们正在使用 Sectigo 代码签名证书 仅 OV 组织验证 而不是 EV 来签署我们的 exe 应用程序 近年来没有出现过问题 现在我们尝试使用相同的证书在 Word Excel 中签署 VBA 但没有成功 当我打开时VBA edito
  • EXPORT AS INSERT 语句:但是在 SQL Plus 中,该行覆盖了 2500 个字符!

    我必须将 Oracle 表导出为 INSERT 语句 但这样生成的 INSERT STATEMENTS 会覆盖 2500 个字符 我必须在 SQL Plus 中执行它们 因此我收到一条错误消息 这是我的 Oracle 表 CREATE TA