大型机CICS中的分页逻辑

时间:2014-02-16 08:01:19

标签: db2 cobol mainframe cics

这是我的要求。

Front(客户端)端将根据预定义的条件进行搜索(例如:客户ID,帐号,名字,姓氏等)。我需要从db2数据库获取与此请求相对应的数据并将其发送回它们(服务器)。我们使用CICS通道和容器在客户端和服务器之间传递请求和响应。

前端需要按以下顺序排列的数据:接收日期降序,客户ID升序,帐号升序。数据以500条记录的页面提取。例如,如果来自前端的搜索请求将从db2数据库中检索50,000条记录,则我们需要在500条记录“页面”中返回此数据。对于分页概念,我们使用字段安全存款号,它是我们数据库的主键,但排序顺序不是基于此字段。

我想知道我们是否可以在CICS中使用可滚动游标逻辑来实现分页。

请注意,我不喜欢使用内部阵列冒泡排序来响应发送数据,因为它会降低性能。我喜欢通过查询逻辑来做。有什么想法吗?

示例(初始前端输入请求):

  • 客户ID:A
  • 第一次请求(以确定它是第一次或下次或以前的分页请求)
  • 首次保证金号码:0
  • 上次保证金号码:0

由于这是第一次请求,因此该字段的前端都为零,我们需要根据保证金条件从数据库中检索记录。 0

Db2数据库:

  • 此条件有700条记录
  • 首次大型机响应: 我们将发送前500条记录

前端将发送获取下一组记录的请求,其中包含:

  • 客户ID:A
  • 下一个请求
  • 首次保证金金额:0
  • 上次保证金号码:17980

所以对于这个细节,如果我根据保证金编号查询我的数据库> 17980,由于数据库中的排序顺序不是基于保证金编号,因此可能会再次在屏幕上列出重复的记录

如何阻止这种逻辑?

2 个答案:

答案 0 :(得分:6)

IBM Mainframe环境中的许多客户端/服务器应用程序涉及伪对话CICS事务。 如果您在psueudo会话模式下使用CICS它 当服务器返回到客户端时,服务器无法保存cusors。因此可滚动的cusors 在这种环境中几乎没用。所以回答你的基本问题:这里不能使用可滚动游标。

"技巧"这是在服务器中创建可重新启动的SQL谓词。然后,它将以任何给定的正确顺序拾取行 说明一点。当客户端调用您的服务器时,它必须将所有定位信息传递给您的服务器。

通常,在客户端的第一次调用中,所有定位值都设置为使光标到达 从必须是第一行的位置开始。然后,服务器提取一个"页面"值得的数据 并将其返回给客户。在下一页转发请求中,客户端将这些定位值设置为 显示的最后一行,并在下一个"页面调用服务器"数据。

在你的情况下,我会假设页面前进光标看起来像这样,所有 以RESTART为前缀的变量...是客户端必须提供给服务器以启动游标的变量 在正确的位置。

 DECLARE CURSOR Page-forward FOR
    SELECT Receive_Date, Customer_id, Account_Nbr, Security_Dep_Id
    FROM Table_Name
    WHERE (   (Receive_Date    < :RESTART-RCV-DT)
           OR (Receive_Date    = :RESTART-RCV-DT AND
               Customer_Id     > :RESTART-CUSTOMER-ID)
           OR (Receive_Date    = :RESTART-RCV-DT AND
               Customer_Id     = :RESTART-CUSTOMER-ID AND
               Account_Nbr     > :RESTART-ACCT-NBR)
           OR (Receive_Date    = :RESTART-RCV-DT AND
               Customer_Id     = :RESTART-CUSTOMER-ID AND
               Account_Nbr     = :RESTART-ACCT-NBR AND
               Security_Dep_Id > :RESTART-SEC-DEP-ID))
    ORDER BY 1 DESC, 2 ASC , 3 ASC, 4 ASC

对于初次通话,客户端会通过类似&#39; 9999-12-31&#39;作为RESTART-RCV-DT,为零 对于RESTART-CUSTOMER-ID,RESTART-ACCT-NBR和SEC-DEP-ID(假设这些都是数字)。如果你看看 仔细检查游标谓词,你可以验证在这些值之前不能有任何行 - 因此 将返回第一页数据。如果客户端在此之后需要向前翻页,它必须告诉服务器启动 收到最后一行之后的下一行。为此,它将填充RESTART ...变量 它只是页面上最后一行的值 显示。此过程将驱动光标一次向前选择一页。

在进行分页时,过程相反(您需要第二个光标来支持此功能,客户端需要告诉您页面的哪个方向:前进或后退)。客户端 将需要使用从服务器收到的第一行填充RESTART变量。诀窍 对于页面上的服务器请求是返回数据 以相反的顺序向客户。您可能必须填充传回的数据页 以相反的顺序向客户端(即将检索到的第一行放入在其间共享的分页区域的最后一行) 客户端和服务器)。页面向后光标看起来像:

 DECLARE CURSOR Page-backward FOR
    SELECT Receive_Date, Customer_id, Account_Nbr, Security_Dep_Id
    FROM Table_Name
    WHERE (   (Receive_Date    > :RESTART-RCV-DT)
           OR (Receive_Date    = :RESTART-RCV-DT AND
               Customer_Id     < :RESTART-CUSTOMER-ID)
           OR (Receive_Date    = :RESTART-RCV-DT AND
               Customer_Id     = :RESTART-CUSTOMER-ID AND
               Account_Nbr     < :RESTART-ACCT-NBR)
           OR (Receive_Date    = :RESTART-RCV-DT AND
               Customer_Id     = :RESTART-CUSTOMER-ID AND
               Account_Nbr     = :RESTART-ACCT-NBR AND
               Security_Dep_Id < :RESTART-SEC-DEP-ID))
    ORDER BY 1 ASC, 2 DESC , 3 DESC, 4 DESC

正如其他答案中所指出的,这种类型的分页过程不管理或检测并发 在寻呼事务中可能发生的数据库更新。那是另一天的另一个话题......

开发可重新启动的游标

构建分页服务器的关键是开发一个可从一组接收的值重新启动的游标 来自客户交易。这样就可以控制客户端的光标定位和方向。 这也意味着即使客户端必须从服务器接收所有关键定位数据 客户可能实际上不是 将这些数据用于任何其他目的(例如,根据您的问题,我得到客户可能不需要的印象 保管存款标识除了作为服务器的定位参数提供外)

要构建您需要知道的分页服务器 所需的数据排序顺序是什么(例如,接收日期降序然后是客户ID升序 帐号升序)。 您还需要知道唯一标识行的数据集 由光标返回。在您的情况下,这将是保证金存款标识(这是主要的密钥) 您正在选择的表,因此该表中的每一行都必须是唯一的。了解这一点,然后建立一个 游标谓词(WHERE子句中的东西),它将以所需的排序顺序返回客户端所需的数据 还包括 完整定位密钥(即安全存款标识)。如果两个或多个返回的行可能包含相同的数据,如果 取消最终定位键使得定位键作为排序条件被包括在内是很重要的。 如果它是升序或降序并不重要,但它需要包含在排序中以确保一致 数据检索的顺序。

可以遵循一个相当简单的公式来为可重启的cusor构建谓词 支持分页服务器。基本上这是一个&#34; OR&#34;连接一系列&#34; AND&#34;的条款条款 根据客户要求的排序顺序逐渐变得更具选择性并最终定位 键。

要了解其工作原理,请考虑如何开发服务器查询...

从最不经常更改的排序顺序开始...

SELECT ... 
FROM ... 
WHERE Receive_Date < restart value

这将检索指定的重新启动接收日期之前的所有行,而不管其他行 列重启值是(例如,客户ID可以从最小值到最大值,只要接收日期 小于任何接收日期&#34;见过&#34;至今)。由于此列仅在所有subortinate排序列值后更改值 如果已经完全重新启动,您可以确保在完全重启键之前不会拾取任何行。 但是那些与重启请求在同一天出现的行却有一个 更大的客户ID?这些可以用....

SELECT ... 
FROM ... 
WHERE Receive_Date = restart value AND
      Customer_id > restart value

接收日期和客户ID与重新启动密钥相同但具有的情况如何? 更大的账号?这些可以用......

获取
SELECT ... 
FROM ... 
WHERE Receive_Date = restart value AND
      Customer_Id = restart value AND
      Account_Nbr > restart value

继续此模式,直到处理完全重启键。注意不平等 标志由排序顺序决定。列排序降序时使用<,升级时列>。 另请注意SELECTFROM条款 对于每个查询都是完全相同的 - 这意味着您可以使用OR结合将它们全部放在一起......

SELECT Receive_Date, Customer_id, Account_Nbr, Security_Dep_Id
FROM Table_Name
WHERE (   (Receive_Date    < :RESTART-RCV-DT)
       OR (Receive_Date    = :RESTART-RCV-DT AND
           Customer_Id     > :RESTART-CUSTOMER-ID)
       OR (Receive_Date    = :RESTART-RCV-DT AND
           Customer_Id     = :RESTART-CUSTOMER-ID AND
           Account_Nbr     > :RESTART-ACCT-NBR)
       OR (Receive_Date    = :RESTART-RCV-DT AND
           Customer_Id     = :RESTART-CUSTOMER-ID AND
           Account_Nbr     = :RESTART-ACCT-NBR AND
           Security_Dep_Id > :RESTART-SEC-DEP-ID))
ORDER BY 1 DESC, 2 ASC , 3 ASC, 4 ASC

你去......一个可重启的游标,用于前向寻呼。用于向后分页的游标的构造遵循类似的模式,只需翻转即可 排序并重复。

答案 1 :(得分:4)

一种简单的方法:根据您指定的排序顺序编写SQL以根据您的条件检索数据。然后仅将键检索到您想要的行。在随后的事务调用中将密钥保存在您可以访问的位置。查看DB2中的多行选择。还要了解CICS中的伪对话编程技术。

现在我们谈到Bill Woodger提到的设计含义,你没有在你的问题中指明,这就是我只是采用简单方法的高点的原因。

如果在一次调用和下一次调用之间发生了对结果集的更改,则结果将不会反映这些更改。你必须决定这是否重要。

你提到了“前端”,但没有具体说明它是什么。如果它是BMS应用程序,您可以将密钥保存在commarea或容器中。如果您的前端是通过CICS Web服务或CICS Web Support或MQ或原始套接字或其他任何方式调用事务的分布式应用程序,则必须设计一种机制来存储这些密钥,以便您可以唯一地检索它们 - 可能通过发送一个人为的密钥返回到后续调用时必须提供的分布式应用程序。然后你必须有一些过程来清理你的密钥库。

在您的IT商店中创建独特的问题解决方案并非孤立无援。您必须让负责维护您的应用程序的其他人参与进来,您的项目可能有一个外部小组负责做出此类决策,您的解决方案可能存在基础架构问题。

所以这不是对你的问题的回答,因为它是对你为什么得不到答案的详细解释,或者至少是你似乎想要的答案。