在循环期间重新初始化PL / SQL中的变量/记录

时间:2011-10-17 11:00:47

标签: loops plsql io

为了为ETL过程创建一个PL / SQL解析器,其中数据主要是位置编码的,我需要逐行读取文件并将记录添加到内存中(包 - (作用域)表进入当前记录或进入新记录。

让我简要解释一下场景和语法规则:我需要解析具有公共标准格式的银行对齐消息(找不到英文文档,只有this和其他意大利文档,而这应该是是欧盟范围的标准)。无论如何,这里解释了一些规则:

  • 文件
  • 中的每条记录长度为120个字符
  • 每个文件都以“AL”(对齐)记录开头
  • 每个文件以en“EF”(文件结束)记录结束
  • 每个对齐消息以“12”记录开头,以“70”记录结束
  • 根据“12”记录的类型,消息可以由其他记录的不同组合组成,例如“30”和“40”,“50”,“45”,“50”和“45” “50”

示例(结构化):

AL record
    12 record
        45 record
    70 record
    12 record
        45 record
        50 record
    70 record
EF record

我已经宣布了一个MESSAGE PL / SQL表CHAR(120),它将封装12到70之间的记录(包括在内),这些记录将在稍后阶段处理。现在我遇到了一个循环问题,我可以用Java轻松解决。

如何在PL / SQL中重新初始化变量?这是我需要做的一个伪Java示例

String line;
List<String> alignment_message;
List<AlignmentMessage> table;
while (line = readline()) {
    if (line.substring(1,2)=="12") //Begin of message 
        alignment_message = new MESSAGE(); //******HOW DO I DO THIS????
    alignment_message.add(line); //Don't care about NPE ;-)

    if (line.substring(1,2)=="70") //End of message
        table.add(alignment_message);
}

我目前在我的PL / SQL过程中声明了msg类型的变量MESSAGE。如果我对此变量执行INSERT,然后我INSERT将此变量放入包含MESSAGE类型列的表中(以及我用于预处理的其他几列) ),如何在新msg变量中执行新的INSERT

由于

2 个答案:

答案 0 :(得分:2)

如果您已将MESSAGE宣布为TABLE OF CHAR(120)TABLE OF CHAR(120) INDEX BY BINARY_INTEGERVARRAY(...) OF CHAR(120),那么您可以

msg.DELETE;

嵌套表,索引表和变量上的DELETE方法会删除它们中的所有元素。

当您INSERT msg进入表格时,Oracle似乎会存储它的副本,而不是对它的引用。删除msg中的所有元素不会导致表格中的数据突然消失。

或者,如果MESSAGETABLE OF CHAR(120)VARRAY(...) OF CHAR(120),您可以调用MESSAGE()构造函数,即

msg := MESSAGE();

答案 1 :(得分:1)

declare
  type message_t is table of char(120);
  v_message message_t := message_t('12 record', /* start */
                                   '40 record',
                                   '70 record', /* end */
                                   '12 record', /* start */
                                   '50 record',
                                   '51 record',
                                   '70 record'  /* end */
                                   );
  v_almessage message_t := message_t();
  v_i number := v_message.first;
begin
  while v_i <= v_message.last loop
    if v_message(v_i) = '12 record' then /* start of a block */
      dbms_output.put_line('start of a block');

      loop
        v_i := v_i + 1;

        if v_message(v_i) = '70 record' then /* end of a block */
          dbms_output.put_line('end of a block');

          /* Do whatever processing you need to do. I just print collected
          messages. */
          for j in v_almessage.first .. v_almessage.last loop
            dbms_output.put_line('aligment message: ' || v_almessage(j)); 
          end loop;

          /* Reset collected messages. */
          v_almessage := message_t();

          exit;
        end if;

        /* Collect block's aligment messages. */
        v_almessage.extend(1);
        v_almessage(v_almessage.last) := v_message(v_i);
      end loop;

    end if;

    v_i := v_i + 1;
  end loop;

end;
/

打印:

start of a block
end of a block
aligment message: 40 record
start of a block
end of a block
aligment message: 50 record
aligment message: 51 record