使用BASH从ORACLE DB读取多个空行的文件

时间:2012-10-08 14:16:37

标签: oracle bash sqlplus

  

可能重复:
  why empty line is not getting stored in variable

我尝试从数据库中读取并输出文本文件。它可以工作但空行将被删除。

实施例

Hello Mr. X

Text from Mailboddy

Greetins
Mr. Y

输出:

Hello Mr. X
Text from Mailboddy
Greetins
Mr. Y

CODE:

sqlplus -s $DBLOGIN <<ENDE_SQL > file
SET FEEDBACK OFF;
SET SERVEROUTPUT ON;
DECLARE
  l_text CLOB;
BEGIN
  SELECT text
    INTO l_text
    FROM table;  
  while dbms_lob.substr(l_text, 1, l_pos) is not null LOOP
    if dbms_lob.substr(l_text, 2, l_pos) = CHR(13) || CHR(10) then
      DBMS_OUTPUT.NEW_LINE;
      l_pos:=l_pos + 1;
    else
      DBMS_OUTPUT.put(dbms_lob.substr(l_text, 1, l_pos));
    end if;
    l_pos:=l_pos + 1;
  END LOOP;
END;
/
ENDE_SQL

PL / SQL代码在SQLDeveloper中使用空行。但是在文件中所有空行都被删除了。

1 个答案:

答案 0 :(得分:1)

假设数据已加载到CLOB中,换行符为CHR(13)||CHR(10),如果您只是直接从表中选择,您可以看到它的预期格式,那么问题在于SQL * Plus是如何与DBMS_OUTPUT进行互动。

默认情况下,SET SERVEROUTPUT ON会将FORMAT设置为WORD_WRAPPED。文档说'SQL * Plus左对齐每条线,跳过所有前导空格',但是没有注意到这也会跳过所有空行。

如果您设置SERVEROUTPUT ON FORMAT WRAPPED... TRUNCATED,则会重新显示空白行。但是你需要确保你的线条足够宽,以便打印出你想要打印的最长线条,特别是如果你选择了TRUNCATED

(此外,您的代码未声明l_pos NUMBER := 1,并且缺少最终DBMS_OUTPUT.NEW_LINE,因此您将从CLOB中丢失最后一行。


为了演示,如果我创建一个仅包含CLOB列的虚拟表,并使用包含回车符/换行符的值填充它,那么您正在寻找:

create table t42(text clob);

insert into t42 values ('Hello Mr. X' || CHR(13) || CHR(10)
    || CHR(13) || CHR(10)
    || 'Text from Mailboddy' || CHR(13) || CHR(10)
    || CHR(13) || CHR(10)
    || 'Greetins' || CHR(13) || CHR(10)
    || 'Mr. Y');

select * from t42;

我明白了:

TEXT
--------------------------------------------------------------------------------
Hello Mr. X

Text from Mailboddy

Greetins
Mr. Y

使用您的程序(经过略微修改以便运行):

sqlplus -s $DBLOGIN <<ENDE_SQL > file
SET FEEDBACK OFF;
SET SERVEROUTPUT ON FORMAT WORD_WRAPPED; -- setting this explicitly for effect
DECLARE
  l_text CLOB;
  l_pos number := 1; -- added this
BEGIN
  SELECT text
    INTO l_text
    FROM t42;
  while dbms_lob.substr(l_text, 1, l_pos) is not null LOOP
    if dbms_lob.substr(l_text, 2, l_pos) = CHR(13) || CHR(10) then
      DBMS_OUTPUT.NEW_LINE;
      l_pos:=l_pos + 1;
    else
      DBMS_OUTPUT.put(dbms_lob.substr(l_text, 1, l_pos));
    end if;
    l_pos:=l_pos + 1;
  END LOOP;
  dbms_output.new_line; -- added this
END;
/

ENDE_SQL

file包含:

Hello Mr. X
Text from Mailboddy
Greetins
Mr. Y

如果我只在代码中更改一行,请执行以下操作:

SET SERVEROUTPUT ON FORMAT WRAPPED;

然后file现在包含:

Hello Mr. X

Text from Mailboddy

Greetins
Mr. Y

您可能需要考虑UTL_FILE,而不是DBMS_OUTPUT,具体取决于您的配置。像this这样的东西可能会给你一些指示。