【问题标题】:Assigning a whole DataStructure its nullind array分配整个数据结构在数组中为空
【发布时间】:2015-04-15 06:09:02
【问题描述】:

问题前的一些上下文。

想象一下文件 FileA 有大约 50 个不同类型的字段。我没有使用该文件的所有程序,而是尝试使用服务程序,因此该文件只能由该服务程序访问。然后,调用该服务的程序将接收基于文件结构的 DataStructure 作为 ExtName。我使用 SQL 来恢复信息,所以,基本上,过程是这样的:

服务程序共享的数据结构:

D FileADS       E  DS                 ExtName(FileA) Qualified

程序调用的过程:

P getFileADS      B                   Export 
D                 PI              N
D  PI_IDKey                      9B 0 Const
D  PO_DS                              LikeDS(FileADS)

D LocalDS       E DS                  ExtName(FileA) Qualified
D NullInd         S              5i 0 Array(50)    <-- Since 50 fields in fileA

 //Code
 Clear LocalDS;
 Clear PO_DS;

 exec sql
   SELECT *
   INTO   :LocalDS :nullind
   FROM   FileA
   WHERE  FileA.ID = :PI_IDKey;

 If SqlCod <> 0;
   Return *Off;
 EndIf;

 PO_DS = LocalDS;
 Return *On;

P getFileADS      E

因此,如果该过程找到它,它将返回一个填充了来自 FileA 的记录的数据结构。

现在我的问题:有什么方法可以在不指定文件的每个 50 个字段的情况下分配 %nullind(field) = *On?

类似循环的东西

 i = 1;
 DoW (i <= 50);
   if nullind(i) = -1;
     %nullind(datastructure.field) = *On;
   endif;
   i++;
 EndDo;

因为让我们面对现实吧,每次都查看每个文件的每个字段会很痛苦。

我知道一个简单的链(n)可以解决问题

 chain(n) PI_IDKey FileA FileADS;

但我真的想用 SQL 来做。

感谢您的建议!

操作系统版本:7.1

【问题讨论】:

  • 我没有给你的答案,但会提供一个建议。与其返回数据结构,不如编写 50 个 getFieldName 过程,分别返回每个字段。肯定有更多的前期设置,但随后您将进一步将文件 i/o 与调用程序分离。走数据结构方法,如果有任何字段改变或增加,所有调用程序都必须重新编译。我和一个老同事写了一个实用程序来为文件创建一个文件封装服务程序,尽管它目前不是共享它的最佳位置。

标签: db2 ibm-midrange rpgle


【解决方案1】:

首先,从长远来看,消除 SELECT * 并提供 50 个字段名称的 SELECT 列表会更好。

接下来,考虑这两个网页——Meaningful Names for Null IndicatorsEmbedded SQL and null indicators。第一个示例显示了为每个空指示符分配名称以匹配关联字段名称的示例。只需根据您的空指标数组的地址,用名称声明一个基于 DS 的问题。第二个指出空指示符数组如何大于所需,因此未来的数据库更改不会影响结果。 (请记住,该页面显示了一个包含 1000 个元素的空数组,即使在那个大小下,内存实际上也相对较小。如果您认为出于某种原因有必要,可以将其声明为更小。)

您正在创建一个只需要编写一次的过程。省去列出 50 个字段的工作是不值得的。也许如果你有很多程序使用这个 proc,并且每次都必须创建列表,那么使用 SELECT * 会有一点帮助,但即使这样也不是一个好主意。

可以在保存 proc 原型的 /COPY 成员中定义 50 个数据字段的匹配模板 DS。模板 DS 将在任何引入 proc 原型的程序中可用。任何需要调用 proc 的程序都可以简单地指定 LIKEDS 引用模板来定义其在内存中的版本。模板 DS 可能应该包含 QUALIFIED 关键字,然后程序将使用它们自己的 DS 名称作为限定前缀。空指标数组也可以类似处理。

但是,您的实际问题是什么并不完全清楚。你展示了一个示例循环并询问它是否可以工作,但你没有说你是否遇到了问题。它是一个数组,因此可以像您展示的那样使用循环。但这取决于你实际上想用它来完成什么。

【讨论】:

  • 事实上,循环是问题的一部分。我正在寻找一种不需要返回 nullind 数组的方法。因为当我将文件数据结构作为参数返回时,%nullind() BIF 会给我正确的值,它将被启动。所以我想知道是否有一种方法可以循环 DS 来分配它的所有 nullind,而不是为所有字段单独执行。是不是更清楚了?另外,我保留了 SELECT * 因为无论文件发生了什么,这个函数应该总是返回每个字段。
  • 虽然它可以'return every field,但这可能会在调用 proc 的程序中冒“不可预测的结果”,除非每个调用模块也重新编译以匹配,或者除非使用了各种保护性编码方法。 “不可预测的结果”可能包括未检测到的数据损坏,这些损坏可能会持续很长时间,可能永远不会被注意到(直到数周/数月后,在一系列可能无法跟踪的错误之后)。如果文件更改导致 proc 返回一个包含 51 个字段的 DS,而调用 proc 只知道大约 50 个字段,那么这些新数据会去哪里?
  • 所以无论如何,我最初的问题是知道是否有一种方法可以设置 DS 的 %nullind(field) 而不列出其每个字段。我应该和你一起理解我不能理解的原始答案吗?
  • @ArnaudMongrain 我继续并发布了答案。 确切地你在问什么并不完全清楚。
  • 今天我会在我的原始帖子中让它更清楚一点,但总体思路是,我正在寻找一种方法来一次将所有 ExtName DS 字段分配到它们的 nullind 数组位置。而不是做类似“%nullind(field1) = nullInArr(1); %nullind(field2) = nullindArr(2);...”的事情。这样会更清楚吗?
【解决方案2】:

对于老式 rpg,只需在使用 select 语句填充的数据结构中包含空值即可。

select col1, ifnull(col1), col2, ifnull(col2), etc.  into :dsfilewithnull where f.id = :id;

对于无法处理空值的老式 rpg,请使用 select 语句将其删除。

select coalesce(col1,0), coalesce(col2,' '), coalesce(col3, :lowdate) into :dsfile where f.id = :id;

第二种方法更容易在旧环境中使用。

将键按值传递给过程,以便您可以像使用内置函数一样使用它。

【讨论】:

    【解决方案3】:

    您的问题的一个答案是将数组作为数据结构的一部分,并将 *all'0' 分配给数据结构。

    dcl-ds nullIndDs;
      nullInd      Ind Dim(50);
    end-ds;
    
    nullIndDs = *all'0';
    

    【讨论】:

      【解决方案4】:

      jmarkmurphy 的回答是将所有零分配给指标数组的示例。对于您在问题中显示的示例,您可以这样做:

       D NullInd         S              5i 0 dim(50)
      
        /free
          NullInd(*) = 1 ;
          Nullind(*) = 0 ;
      
          *inlr = *on ;
          return ;
        /end-free
      

      这是一个完整的程序,您可以编译和测试。在调试中运行它并在第一条语句处停止。显示 NullInd 以查看其元素的初始值。单步执行第一个语句并再次显示它以查看元素如何更改。单步执行下一条语句,看看情况如何再次发生变化。

      至于“如何在 SQL 中做到这一点”,那部分没有意义。当您 FETCH 一行时,SQL 会自动设置这些值。除此之外,宿主语言(在本例中为 RPG)使用该数组将值传回 SQL。当一条 SQL 语句运行时,它会再次自动使用设置的任何值。因此,它要么由 SQL 自动用于输入或输出,要么由您的宿主语言语句设置。使用该数组“在 SQL 中”没有任何用处。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-13
        • 1970-01-01
        • 2014-04-21
        相关资源
        最近更新 更多