【问题标题】:CSV exporting causing ORA-01489CSV 导出导致 ORA-01489
【发布时间】:2018-08-12 18:17:02
【问题描述】:

我正在使用假脱机工具将数据从我的 Oracle 10g 数据库导出到 CSV 文件。然而,在导出几行,184170 行后,我收到以下错误:

错误: ORA-01489: 字符串连接的结果太长

我的表中有一个字段 FIELD2,它是 VARCHAR2(4000 BYTE) 类型,我有一些包含 4000 个字符的行。 我的选择请求如下:

select FIELD1 ||'|'||FIELD2 ||'|'||FIELD3 from table;

有什么办法可以不用截断 FIELD2 吗?

所以问题是因为我的选择请求太长了。下面是生成请求的函数:

create or replace FUNCTION build_select (
  p_table_name   IN VARCHAR2
)
    RETURN VARCHAR2
AS
    l_ret   VARCHAR2 (32767);
BEGIN
    FOR eachcol IN (  SELECT column_name, data_type
                           , LEAD (column_name)
                                 OVER (
                                     PARTITION BY table_name ORDER BY column_id
                                 )
                                 next_column
                        FROM all_tab_cols
                       WHERE table_name = p_table_name
                    ORDER BY column_id)
    LOOP
      IF eachcol.data_type = 'CLOB' THEN
        l_ret   := l_ret || 'dbms_lob.substr( '||eachcol.column_name||', 3000, 1 )'|| CASE WHEN eachcol.next_column IS NULL THEN NULL ELSE ' ||''|''||' END;
      ELSE 
        l_ret   := l_ret || eachcol.column_name|| CASE WHEN eachcol.next_column IS NULL THEN NULL ELSE ' ||''|''||' END;
      END IF;
    END LOOP;

    IF l_ret IS NULL
    THEN
        raise_application_error (-20001, 'table ' || p_table_name || ' not found');
    END IF;

    l_ret   := 'select ' || l_ret || ' from ' || p_table_name || ';';

    RETURN l_ret;
END build_select;

【问题讨论】:

  • 使用SET colsep '|' 获取管道分隔的记录。以select field1,field2,field3 from table 的形式运行查询
  • @KaushikNayak:不,我不能这样做,因为我有一个函数可以像这样构建我的选择请求。
  • 然后改变你的功能。否则你可能不得不使用CLOB
  • @KaushikNayak:这就是我的问题所在。如果我使用 CLOB,生成的 csv 将不包含所有行。我正在使用 dbms_lob.substr 函数导出 CLOB。
  • 您在问题中的什么地方解释说您有一个函数或“使用dbms_lob.substr 导出 CLOB?清楚地解释您想要实现的目标并提供一些可能有用的问题背景找到解决方案并避免混淆。

标签: oracle export-to-csv


【解决方案1】:

你说

FIELD2,在我的表中是 VARCHAR2(4000 BYTE),你有一些行 包含 4000 个字符,

将列选择为select field1,field2,field3 时不会出现问题。但是,因为您使用“|”将它们连接在一起,最终字符串超过 4000 个字符,这是 VARCHAR2 列的限制。因此,Oracle 会抛出错误,因为您甚至不能拥有具有隐式数据类型 VARCHAR2 的别名列,该列超过 4000 个字符。

一种选择是使用

set colsep '|' 

在您的 SQL* Plus 会话中,只需将其选择为

select field1,field2,field3 from yourtable.

另一种选择是使用TO_CLOB 函数将结果显式转换为CLOB

select TO_CLOB(NULL)||FIELD1 ||'|'||FIELD2 ||'|'||FIELD3 from table;

DEMO

【讨论】:

  • 所以你的意思是它的形式是 DATA1||DATA2||DATA3 超过 4000 个字符的结果导致了这个错误?
  • @tabby:没错。为什么它让你如此困惑?只需为 4000 个字符长的记录运行 select field2 from yourtable,它是否对您不起作用?
  • 问题是我需要我的选择请求采用 DATA1||DATA2||DATA3 的形式,以减少生成的 CSV 的大小。我有一个功能可以做到这一点。对于 CLOB 类型,我的函数中有一个条件: IF eachcol.data_type = 'CLOB' THEN l_ret := l_ret || 'dbms_lob.substr('||eachcol.column_name||', 3000, 1)'|| CASE WHEN eachcol.next_column 为 NULL THEN NULL ELSE '||''|''||'结尾;也许我可以尝试类似的东西?
  • @tabby :如果是这种情况,您应该使用功能代码部分更新您的问题,并详细说明您如何生成选择语句。也许,您可能还需要修改您的函数。
  • 好的,我修改了问题。
猜你喜欢
  • 2012-05-12
  • 2017-02-06
  • 1970-01-01
  • 2015-07-15
  • 2020-02-21
  • 2014-04-16
  • 2017-04-15
  • 1970-01-01
  • 2013-05-06
相关资源
最近更新 更多