IBM 大型机环境中的许多客户端/服务器应用程序都涉及伪会话 CICS 事务。如果您在伪会话模式下使用 CICS,则服务器在返回给客户端时不可能持有游标。因此,可滚动光标在这种环境中用处不大。因此,要回答您的基本问题:此处不能使用任何可滚动光标。
这里的“技巧”是在可重新启动的服务器中创建一个 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
对于初始呼叫,客户端将传递类似“9999-12-31”的内容作为 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,除非提供作为服务器的定位参数)
要构建分页服务器,您需要知道所需的数据排序顺序是什么(例如,接收日期降序,然后客户 ID 升序,然后帐号升序)。您还需要知道唯一标识游标返回的行的数据集。在您的情况下,这将是安全存款 ID(这是您从中选择的表的主键,因此该表中的每一行都必须是唯一的)。知道这一点后,您就可以构建一个游标谓词(WHERE 子句中的内容),它将以所需的排序顺序返回客户端所需的数据,其中还包括完整的定位键(即安全存款 ID)。如果两个或更多返回的行可能包含相同的数据,如果最终定位键被消除,那么将定位键作为排序条件包括在内是很重要的。
可以遵循一个相当简单的公式来为支持分页服务器所需的可重新启动的游标构建谓词。基本上,这是连接一系列“AND”子句的“OR”子句的级联,这些子句按照客户端要求的排序顺序逐渐变得更有选择性,最终得到定位键。
要了解这是如何工作的,请考虑如何开发您的服务器的查询......
从排序顺序中更改频率最低的列开始...
SELECT ...
FROM ...
WHERE Receive_Date < restart value
这将检索指定重新开始接收日期之前的所有行,而不管其他列重新开始值是什么(例如,客户 ID 的范围可以从最小值到最大值,只要接收日期小于到目前为止“看到”的任何接收日期)。由于此列仅在所有从属排序列的值被耗尽后才更改值,因此您可以确保这不会在完全重新启动键之前拾取任何行。但是那些与重新启动请求在同一日期出现但具有更大客户 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
继续此模式,直到处理完完整的重新启动密钥。请注意,不等号由排序顺序决定。<
当列按降序和升序排序时使用>
。另请注意,每个查询的SELECT
andFROM
子句完全相同 - 这意味着您可以使用 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
你去...一个用于向前分页的可重新启动光标。向后分页光标的构造遵循类似的模式,只需翻转排序顺序并重复。