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

发布于 2024-12-10 00:21:23 字数 1520 浏览 1 评论 0原文

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

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

  • 文件中的每条记录长度为 120 个字符
  • 每个文件以“AL”(对齐)记录开头
  • 每个文件以“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

我已经声明了 CHAR(120)MESSAGE PL/SQL 表,该表将封装 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 过程中声明一个 MESSAGE 类型的变量 msg。如果我对此变量执行 INSERT 操作,然后将此变量 INSERT 插入包含 MESSAGE 类型列(以及一对我用于预处理的其他列),如何将新的 INSERT 执行到 fresh 新的 msg 变量中?

谢谢

In order to create a PL/SQL parser for an ETL process, in which data is mainly positional-encoded, I have the need to read a file line-by-line and add records to an in-memory (package-scoped) table into the current record or into a new record.

Let me briefly explain the scenario and the grammar rules: I need to parse banking alignment messages, which have a public standard format (can't find English documentation, only this and other Italian documents, while this should be an EU-wide standard). Anyway here are some rules explained:

  • Each record is 120 characters long in the file
  • Every file begins with an "AL" (ALignment) record
  • Every file ends with en "EF" (End of File) record
  • Each alignment message begins with a "12" record and ends with a "70" record
  • Depending on the type of the "12" record, the message can be made of different combinations of other records, like "30" and "40", "50", "45", "50" and "45" "50"

Example (structured):

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

I already declared a MESSAGE PL/SQL table of CHAR(120), which shall encapsulate records between 12 and 70 (included), those will be processed in a later stage. Now I have a looping problem that I could easily solve in Java.

How can I reinitialize a variable in PL/SQL? Here is a pseudo-Java example of what I need to do

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);
}

I have currently declared, in my PL/SQL procedure, a variable msg of type MESSAGE. If I do an INSERT into this variable, and then I INSERT this variable into a table that contains a column of type MESSAGE (and a couple of other columns I use for pre-processing), how can I perform new INSERTs into a fresh new msg variable?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无边思念无边月 2024-12-17 00:21:23

如果您已将 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();

If you've declared MESSAGE as TABLE OF CHAR(120), TABLE OF CHAR(120) INDEX BY BINARY_INTEGER or VARRAY(...) OF CHAR(120), then you can do

msg.DELETE;

The DELETE methods on nested tables, index-by tables and varrays delete all elements from them.

When you INSERT msg into a table, Oracle appears to store a copy of it, rather than a reference to it. Deleting all of the elements from msg won't cause data in your table to suddenly disappear.

Alternatively, if MESSAGE is a TABLE OF CHAR(120) or a VARRAY(...) OF CHAR(120), you can call the MESSAGE() constructor, i.e.

msg := MESSAGE();
断肠人 2024-12-17 00:21:23
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
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;
/

Prints:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文