Db2 将整个数据结构分配给其nullind数组

Db2 将整个数据结构分配给其nullind数组,db2,ibm-midrange,rpgle,Db2,Ibm Midrange,Rpgle,问题之前的一些背景 想象文件FileA有大约50个不同类型的字段。我尝试使用一个服务程序,而不是所有使用该文件的程序,因此该文件只能由该服务程序访问。调用该服务的程序随后将接收一个基于文件结构的数据结构,作为ExtName。我使用SQL恢复信息,因此,基本上,过程如下: 服务程序共享的数据结构: D FileADS E DS ExtName(FileA) Qualified 程序调用的过程: P getFileADS B

问题之前的一些背景

想象文件FileA有大约50个不同类型的字段。我尝试使用一个服务程序,而不是所有使用该文件的程序,因此该文件只能由该服务程序访问。调用该服务的程序随后将接收一个基于文件结构的数据结构,作为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
但我真的想用SQL来实现它

谢谢你的建议


操作系统版本:7.1

首先,从长远来看,通过删除
SELECT*
并提供一个包含50个字段名的SELECT列表,您会受益匪浅

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

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

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


然而,你的实际问题并不完全清楚。您展示了一个示例循环,并询问它是否有效,但您并没有说是否有问题。它是一个数组,所以可以像您所展示的那样使用循环。但这取决于您实际试图用它完成的任务。

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

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

对于无法处理空值的旧式rpg,请使用select语句删除它们。

select col1, ifnull(col1), col2, ifnull(col2), etc.  into :dsfilewithnull where f.id = :id;
select coalesce(col1,0), coalesce(col2,' '), coalesce(col3, :lowdate) into :dsfile where f.id = :id;
第二种方法更易于在遗留环境中使用


将key by value传递给过程,以便您可以像使用内置函数一样使用它。

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

dcl-ds nullIndDs;
  nullInd      Ind Dim(50);
end-ds;

nullIndDs = *all'0';

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

 D NullInd         S              5i 0 dim(50)

  /free
    NullInd(*) = 1 ;
    Nullind(*) = 0 ;

    *inlr = *on ;
    return ;
  /end-free
这是一个可以编译和测试的完整程序。在debug中运行它,并在第一条语句处停止。显示NullInd以查看其元素的初始值。单步执行第一条语句并再次显示,以查看元素是如何更改的。逐步浏览下一个语句,查看情况如何再次发生变化


至于“如何在SQL中实现”,这一部分毫无意义。SQL在获取行时自动设置值。除此之外,主机语言(本例中为RPG)使用数组将值传回SQL。当SQL语句运行时,它会再次自动地使用设置的任何值。因此,它要么由SQL自动用于输入或输出,要么由宿主语言语句设置。“在SQL中”使用该数组没有什么有用的功能。

我没有答案,但会提供一个建议。与其返回数据结构,不如编写50个getFieldName过程,分别返回每个字段。肯定会有更多的前期设置,但是接下来您需要进一步将文件i/o与调用程序解耦。通过使用数据结构方法,如果任何字段发生更改或添加,则必须重新编译所有调用程序。我和一位老同事编写了一个实用程序,为一个文件创建一个文件封装服务程序,尽管它目前不是共享文件的最佳位置。事实上,循环是问题的一部分。我正在寻找一种不需要返回nullind数组的方法。因为当我将文件数据结构作为参数返回时,%nullind()BIF将为我提供正确的值,它将被启动。所以我想知道是否有一种方法可以循环DS来分配它的所有null ind,而不是单独为所有字段分配。更清楚吗?此外,我保留了SELECT*,因为无论文件发生什么情况,该函数都应该始终返回每个字段。尽管它可以返回每个字段,但在调用proc的程序中可能会出现“不可预测的结果”,除非每个调用模块也被重新编译以匹配,或者除非使用了各种保护性编码方法。“不可预测的结果”可能包括未检测到的数据损坏,这些损坏可能会持续很长时间,可能永远不会被注意到(直到数周/数月后,在一系列可能无法跟踪的错误之后)。如果文件更改导致proc返回一个包含51个字段的DS,而调用proc只知道大约50个字段,那么新数据将流向何处?因此,我最初的问题是,是否有办法设置DS的%nullind(字段),而不列出其每个字段。“我能理解你最初的答案吗?我不能?”阿诺蒙格伦我继续写了一个答案。那不是com