DL/I 예제
상위 세그먼트 내에서 검색
기본 get next 문은 데이터베이스의 현재 위치에서 시작하며 상위 아래에 있는 대상 세그먼트의 다음 발생에 대해 전체 데이터베이스를 검색합니다. 검색 범위를 현재 설정된 종속자 체인으로 제한하려면 get next inParent 문을 사용하십시오.
get myOrder with #dli {
GU STSCCST (STQCCNO = :myCustomer.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
STSOCORD (STQCODN = :myOrder.orderDateno) };
get next inParent myItem;
while (myItem not noRecordFound)
// 현재 항목 처리
get next inParent myItem;
end
GNP STLCITM
다른 키가 아닌 필드로 검색
- 신용 세그먼트(STSCSTA)에서 creditBalance 필드(STFCSBL)를 검색하려고 합니다. 이를 수행하려면 검색하려는 지정된 양을 포함하는 10진수 유형(12,2)의 변수를 정의하십시오(예: "targetBalance"). targetBalance에 대한 정의는 신용 세그먼트에서 creditBalance 필드에 대한 정의와 일치해야 합니다.
- myCrStatus 레코드에 대해 get next 문을 작성하십시오.
- 기본 코드를 수정하여 행에 #dli 지시문을 추가하십시오. creditBalance 필드의 양이 targetBalance보다 큰 세그먼트를 찾는 규정된 SSA를 추가하십시오.
- 신용 세그먼트에 해당하는 고객 세그먼트(STSCCST)를 검색하도록 경로 명령 코드(*D)를 포함시키십시오.
targetBalance decimal(12,2);
targetBalance = 10,000.00;
get next myCustomer,myCrStatus with #dli{
GU STSCCST*D STSCSTA (STFCSBL >= :targetBalance) };
다른 레코드의 정보를 기반으로 검색
Record CustomerData type basicRecord
10 customerNo char(6)
...
end
Program myProgram
(customerParm CustomerData)
{ @DLI{ psb = "myCustomerPSB" }}
//변수 선언
myCustomerPSB CustomerPSBRecordPart;
myCustomer CustomerRecordPart;
- 다음과 같이 customerParm.customerNo의 값을 myCustomer.customerNo에 지정한 후
암시적 DL/I I/O를 사용하십시오.
myCustomer.customerNo = CustomerParm.customerNo; get myCustomer;이 경우 EGL은 정상적인 기본 SSA를 작성하고 그 결과 다음과 같은 의사 DL/I 코드가 만들어집니다.
이 기술의 장점은 매우 단순하다는 것입니다. 단점은 고객 번호를 세그먼트 레코드에 이동하는 데 성능 오버헤드가 아주 약간 발생한다는 점입니다.GU STSCCST (STQCCNO = :myCustomer.customerNo) - 다음과 같이 #dli 지시문 및 명시적 DL/I I/O를 사용하면
customerParm.customerNo 필드를 호스트 변수로 사용할 수 있습니다.
이 기법은 고객 번호 이동에 따른 성능 오버헤드를 막아줍니다. 그러나 기본 #dli 지시문에 붙여넣기하는 시간이 다소 길어지므로 코드를 수정하여 매개변수 레코드에 정확한 레코드 변수 이름을 사용하십시오.get myCustomer with #dli { GU STSCCST (STQCCNO = :customerParm.customerNo) } ; - 다음과 같이 DLISegment 레코드에서
hostVarQualifier 특성을 추가하여
호스트 변수에 대한 규정자를 지정하십시오.
Record CustomerRecordPart type DLISegment {segmentName="STSCCST", keyItem="customerNo", hostVarQualifier="customerParm" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; // 키 필드 ... end그러면 다음과 같이 customerParm.customerNo를 myCustomer.customerNo에 먼저 지정하지 않고 암시적 DL/I I/O를 사용할 수 있습니다.get myCustomer;이 경우 EGL이 작성하는 의사 DL/I 코드는 다음과 같습니다.GU STSCCST (STQCCNO = :customerParm.customerNo)이 기법의 이점은 #dli 지시문을 직접 코드화하지 않아도 #dli 지시문에 대해 코드화해둔 동일한 의사 DL/I 코드가 얻어진다는 것입니다. 단점은 EGL이 이제 CustomerRecordPart를 사용하는 모든 암시적 DL/I 데이터베이스 I/O 문에 대한 규정자로 customerParm을 사용한다는 것입니다.
비루트 세그먼트 검색
암시적 DL/I 데이터베이스 I/O를 사용하여 비루트 세그먼트를 검색할 수 있습니다. EGL은 PCB에서 대상 세그먼트의 계층 구조 위치를 기반으로 전체 SSA 체인을 작성합니다. 그러나 계층 구조의 상위 레벨 세그먼트에 대해서는 EGL이 세그먼트에 대한 규정자로 사용할 프로그램 변수의 이름을 자동으로 판별할 수 없습니다.
myCustomer CustomerRecordPart;
myLocation LocationRecordPart;
get myLocation;
EGL이
다음 의사 DL/I 코드를 작성합니다. GU STSCCST (STQCCNO = :CustomerRecordPart.customerNo)
STSCLOC (STQCLNO = :myLocation.locationNo)
EGL이 변수 myLocation을 세그먼트 STSCLOC와 올바르게 연관시켰으나 EGL이 CustomerRecordPart를 기반으로 하는 변수 myCustomer를 찾을 수 없었습니다. EGL은 myLocation이 LocationRecordPart 유형이고 이 유형의 상위 세그먼트가 CustomerRecordPart이며, CustomerRecordPart의 keyItem이 customerNo라는 것만 알고 있습니다.
- 기반으로 하는 레코드 파트와 동일한 이름으로 레코드 변수를
이름 지정할 수 있습니다. 예를 들어, myCustomer의 변수 선언을
CustomerRecordPart로 변경하십시오.
EGL이 동일한 의사 DL/I 코드를 작성합니다.CustomerRecordPart CustomerRecordPart;GU STSCCST (STQCCNO = :CustomerRecordPart.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo)EGL이 PCB 계층 구조 정보에서 기본 SSA를 작성하므로 이는 EGL이 사용하는 변수 이름을 사용자 프로그램의 레코드 변수 선언과 일치시키는 간단한 방법입니다. 단점은 이 기법은 파트와 변수에 다른 이름을 사용하는 일반 사례를 따르지 않는다는 점입니다.
- 다음과 같이 #dli 지시문 및 명시적 DL/I 데이터베이스 I/O를 사용하십시오.
get myLocation with #dli { GU STSCCST (STQCCNO = :myCustomer.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo)이 기술의 장점은 사용되는 호스트 변수가 매우 분명하다는 점입니다. 호스트 변수 규정자 또는 필드 이름이 DL/I 세그먼트 레코드를 기반으로 하는 레코드 변수와 다른 경우 이는 사용하기 쉬운 기술입니다. 단점은 명시적 I/O의 경우와 동일합니다. 즉, 계층 구조나 키 필드가 변경되는 경우 명시적 DL/I 데이터베이스 I/O 문이 자동으로 변경되지 않습니다.
- 다음과 같이 hostVarQualifier 특성을 포함하도록
CustomerRecordPart의 정의를 수정하십시오.
현재 다음 get 문을 사용하는 경우:Record CustomerRecordPart type DLISegment { segmentName="STSCCST", keyItem="customerNo", hostVarQualifier = "myCustomer" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; // 키 필드 ... end
EGL이 올바른 의사 DL/I 코드를 생성합니다.get myLocation;GU STSCCST (STQCCNO = :myCustomer.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo)이 기술의 장점은 암시적 DL/I 데이터베이스 I/O을 사용할 수 있고 레코드 변수와 DL/I 세그먼트 레코드에 대해 서로 다른 이름을 가질 수 있다는 점입니다. 단점은 EGL이 이제 CustomerRecordPart를 사용하는 모든 암시적 DL/I 데이터베이스 I/O 문에 대한 규정자로 myCustomer를 사용한다는 것입니다.
2차 색인으로 검색
// 이름별 고객 데이터베이스 PCB
customerNamePCB DB_PCBRecord
{ @PCB { pcbType = DB, pcbName = "STDCNAM",
secondaryIndex = "STUCCNM",
hierarchy = [ @relationship { segmentRecord = "CustomerRecordPart" },
... ] }
}
pcbName 특성은 런타임 PSB의 실제 DL/I 데이터베이스 PCB와 일치해야 합니다. secondaryIndex 특성은 데이터베이스 관리자가 런타임 PCB의 XDFLD문에 지정한 것과 동일한 필드 이름을 제공해야 합니다. 이제 PSB 레코드에는 계층 구조에 CustomerRecordPart를 포함하는 두 개의 PCB 레코드가 있습니다.
myCustomer CustomerRecordPart;
get myCustomer;
EGL은 CustomerRecord 파트를 포함하는
PSB 레코드의 첫 번째 PCB 레코드를 기반으로
의사 DL/I 코드를 작성합니다.get myCustomer usingPCB customerNamePCB;
EGL이
다음 의사 DL/I 코드를 작성합니다. GU STSCCST (STUCCNM = :myCustomer.customerName)
- 세그먼트의 DL/I 이름(특성 segmentName = "STSCCST")
- 2차 색인 필드의 DL/I 이름(특성 secondaryIndex = "STUCCNM")
- 비교 값의 EGL 필드 이름(특성 dliFieldName = "STUCCNM" 및 해당 필드 이름 customerName)
// 고객 데이터베이스의 오더 보기
ordersByReferencePCB DB_PCBRecord
{ @PCB { pcbType = DB, pcbName = "STDCDBL",
secondaryIndex = "STFCORF", // DL/I 이름 사용
hierarchy = [
@relationship { segmentRecord = "OrderRecordPart" },
@relationship { segmentRecord = "LocationRecordPart",
parentRecord = "OrderRecordPart" },
@relationship { segmentRecord = "CustomerRecordPart",
parentRecord = "LocationRecordPart" },
@relationship { segmentRecord = "ItemRecordPart",
parentRecord = "OrderRecordPart" }
]}
};
end
get myOrder, myCustomer with #dli{
GU STPCORD*D (STQCODN = :myOrder.orderReference)
STSCLOC
STSCCST };
경로 호출을 사용하여 다중 세그먼트 액세스
get myCustomer, myLocation, myOrder;
이 명령문은
다음 DL/I 의사 코드를 생성합니다. GU STSCCST*D (STQCCNO = :myCustomer.customerNo)
STSCLOC*D (STQCLNO = :myLocation.locationNo)
STPCORD (STQCDDN = :myOrder.orderDateNo)
get myCustomer, myLocation, myOrder forUpdate;
replace myOrder with #dli{
REPL STSCCST*N
STSCLOC*N
STPCORD };
D 명령 코드와 함께 get forUpdate 문을 따르는
delete 함수에 대한
기본 DL/I 호출 EGL 빌드는 검색된 각 세그먼트를
삭제하지 않습니다. 이는
delete 문에서 지정된 대상 세그먼트만 삭제합니다.단일 I/O 문으로 모든 세그먼트 읽기
- 데이터베이스에서 최대 세그먼트를 나타내는 레코드에 대해 get next 문을 쓰십시오. 이는 사용자가 읽는 세그먼트가 할당된 메모리를 초과하지 않게 해줍니다.
- 기본 DL/I 호출을 코드에 추가하십시오. 단일 SSA를 삭제하도록 #dli 지시문을 편집하십시오.
- 데이터베이스에서 기타 세그먼트와 일치하는 레코드를 작성하십시오. 프로그램에서 레코드를 선언하고 각 레코드가 위의 1단계에서 사용된 레코드를 재정의하도록 지정하여 모든 레코드가 동일한 메모리 영역을 점유하게 하십시오.
- get next 문 뒤에 dliVar.segmentName을 선택하여 검색된 세그먼트 유형을 판별하십시오.
- 해당 레코드 구조에서 검색된 세그먼트에 액세스하십시오.
myHistory HistoryRecordPart
redefCustomer CustomerRecordPart {redefines=myHistory};
redefLocation LocationRecordPart {redefines=myHistory};
...
//유형에 상관 없이 히스토리 레코드로 다음 세그먼트 읽기
while (myHistory not EOF)
get next myHistory with #dli{
GN };
//어떤 유형?
case (dliVar.segmentName)
when "STSCCST" // 고객임
printCustomer();
when "STSCLOC" // 위치임
printLocation();
...
endend
동적 배열 사용
get 및 get next 문을 사용하여 동적 배열에 대해 DL/I 세그먼트를 검색할 수 있습니다. 배열 자체에 대한 키 필드가 없으므로(배열 멤버에만 해당) EGL이 올바른 코드를 작성하도록 특별한 기술을 사용해야 합니다.
myCustomer CustomerRecordPart;
myLocation LocationRecordPart;
myOrder OrderRecordPart;
myOrderArray OrderRecordPart [] {maxsize = 20}; // 주문 배열
myCustomer.customerNo = "123456";
myLocation.locationNo = "ABCDEF";
myOrderDateNo = "20050730A003";
get myOrderArray; // 먼저 배열 채우기
... do some processing
get next myOrderArray; // 20개의 주문으로 된 다음 일괄처리 가져오기
get myOrderArray with #dli{
GU STSCCST (STQCCNO = :CustomerRecordPart.customerNo)
STSCLOC (STQCLNO = :LocationRecordPart.locationNo)
STPCORD (STQCODN = :OrderRecordPart.orderDateNo)
GN STPCORD };
get next myOrderArray with #dli{
GN STPCORD };
get 문을 사용하여 20개 주문으로 된 첫 번째 일괄처리의 동적 배열을 채우려면 초기 GU 호출 이후 배열이 가득 차거나 DL/I에서 세그먼트 발생이 없어질 때까지 GN 호출이 계속 이어져야 합니다. EGL이 작성하는 의사 DL/I 코드에서 GU 호출은 첫 번째 주문 세그먼트를 검색합니다. EGL은 GN 호출을 루프로 처리하고 배열이 가득 차거나 DL/I에서 세그먼트 발생이 없어질 때까지 루프에 로직을 제공합니다. 마찬가지로 EGL은 get next 문을 루프로 처리하며 루프 제어 로직을 제공합니다.
- DL/I 데이터베이스의 세그먼트와 동일한 이름으로 DL/I 세그먼트 레코드의 이름을 지정하십시오. 또한 DL/I 데이터베이스의 세그먼트와 동일한 이름이 되도록 사용자의 레코드 변수 이름을 변경하십시오. 예를 들어, 다음에서 고객 레코드 파트 정의를 변경하십시오.
다음으로 변경하십시오.Record CustomerRecordPart type DLISegment { segmentName="STSCCST", keyItem="customerNo" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; // 키 필드 ... endRecord STSCCST type DLISegment { segmentName="STSCCST", keyItem="customerNo" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; // 키 필드 ... end위치 세그먼트(STSCLOC) 및 주문 세그먼트(STPCORD)에 대해서도 이와 같이 변경하십시오. 그런 다음, 다음과 같이 새 이름을 사용하도록 PSB 레코드를 변경하십시오.Record CustomerPSBRecordPart type PSBRecord { defaultPSBName="STBICLG" } // 데이터베이스 PCB customerPCB DB_PCBRecord { @PCB { pcbType = DB, pcbName = "STDCDBL", hierarchy = [ @relationship { segmentRecord = "STSCCST" }, @relationship {segmentRecord="STSCLOC", parentRecord="STSCCST"}, @relationship {segmentRecord="STPCORD", parentRecord="STSCLOC"} ]}}; end다음과 같이 레코드 변수와 myOrderArray의 선언을 변경하여 새 DL/I 세그먼트 레코드 파트를 참조하게 하십시오.STSCCST STSCCST; STSCLOC STSCLOC; STPCORD STPCORD; myOrderArray STPCORD [] {maxsize = 20}; // 주문 배열이제 다음 get 문을 실행하는 경우:
EGL이 get 문에 대해 다음 의사 DL/I 코드를 작성하고 호스트 변수 규정자는 올바른 레코드 변수 이름을 사용합니다.get myOrderArray; // 먼저 배열 채우기get myOrderArray with #dli{ GU STSCCST (STQCCNO = :STSCCST.customerNo) STSCLOC (STQCLNO = :STSCLOC.locationNo) STPCORD (STQCODN = :STPCORD.orderDateNo) GN STPCORD };EGL이 PCB 계층 구조 정보에서 기본 SSA를 작성하므로 이는 EGL이 사용하는 변수 이름을 사용자 프로그램의 레코드 변수 선언과 일치시키는 간단한 방법입니다. 단점은 파트와 변수에 다른 이름을 사용하는 일반 사례를 따르지 않는다는 점입니다.
- 다음과 같이 #dli 지시문 및 명시적 DL/I 데이터베이스 I/O를 사용하십시오.
get myOrderArray with #dli{ GU STSCCST (STQCCNO = :myCustomer.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo) STPCORD (STQCODN = :myOrder.orderDateNo) GN STPCORD };이 기술의 장점은 사용되는 호스트 변수가 매우 분명하다는 점입니다. 이 기술은 기본 DL/I 코드를 변경해야 하는 경우(예를 들어, 고객의 첫 번째 주문 번호를 모르는데 다음 DL/I 코드를 사용하려고 하는 경우) 특히 유용합니다.myOrder.orderDateNo = ""; get myOrderArray with #dli{ GU STSCCST (STQCCNO = :myCustomer.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo) STPCORD (STQCODN >= :myOrder.orderDateNo) // 대신 >= 사용 GN STPCORD };이 기술의 단점은 명시적 I/O의 경우와 동일합니다. 즉, 계층 구조나 키 필드가 변경되어도 명시적 DL/I 데이터베이스 I/O 문이 자동으로 변경되지 않습니다.
- 각 DL/I 세그먼트 레코드의 정의를 수정하여 사용자 프로그램 레코드 변수의 이름과 함께 hostVarQualifier 특성을 포함시키십시오. 예를 들어, CustomerRecordPart를 다음으로 변경하십시오.
Record CustomerRecordPart type DLISegment { segmentName="STSCCST", keyItem="customerNo", hostVarQualifier = "myCustomer" } 10 customerNo char(6) { dliFieldName = "STQCCNO" }; // 키 필드 ... end다음 레코드 선언 및 get 문을 사용하는 경우:myCustomer CustomerRecodPart; myLocation LocationRecordPart; myOrder OrderRecordPart; myOrderArray OrderRecordPart [] {maxsize = 20}; // 오더 배열 get myOrderArray; // 먼저 배열 채우기EGL이 올바른 의사 DL/I 코드를 생성합니다.get myOrderArray with #dli{ GU STSCCST (STQCCNO = :myCustomer.customerNo) STSCLOC (STQCLNO = :myLocation.locationNo) STPCORD (STQCODN = :myOrder.orderDateNo) GN STPCORD };이 기술의 장점은 암시적 DL/I 데이터베이스 I/O을 사용할 수 있고 레코드 변수와 DL/I 세그먼트 레코드에 대해 서로 다른 이름을 가질 수 있다는 점입니다. 단점은 EGL이 이제 CustomerRecordPart, LocationRecordPart, OrderRecordPart를 사용하는 모든 암시적 DL/I 데이터베이스 I/O 문에 대한 규정자로 myCustomer를 사용한다는 것입니다.