< 이전 | 다음 >

학습 3: openforEach로 커서 관리

커서는 책갈피와 같이 동작하는 SQL 구성으로서, 행을 가리키고 사용자가 한 번에 하나씩 일련의 검색 결과(즉, 테이블 행)를 단계적으로 이동할 수 있도록 합니다. EGL이 커서를 관리할 수 있지만 커서를 이용하도록 openforEach 문도 제공합니다.

이전 학습에서 delete 문이 키워드 noCursor를 포함하고 있다는 것을 인지했을 것입니다. get 문이 전체 테이블에서 하나 이상의 행을 선택하는 반면, delete문은 일반적으로 이전 명령문에서 작성한 커서가 표시하는 행에 대해서만 작동합니다. noCursor 키워드는 해당 커서가 존재하지 않으며 명령문이 기본 get 문과 같은 방식으로 WHERE절을 사용하여 행을 식별해야 한다는 것을 나타냅니다.

EGL open 문은 커서를 작성하고 커서가 이동할 수 있는 하나 이상의 행 세트 또는 결과 세트를 표시합니다. 커서에 직접 액세스하지 않고 다른 EGL 문을 사용하여 커서가 표시하는 대로 결과 세트에서 다음 행을 검색하거나 커서를 사용하여 한 번에 한 행을 단계적으로 이동하여 전체 결과 세트에서 조작을 수행합니다.

EGL로 커서 및 결과 세트를 작성하려면 open 문을 사용하여 하나 이상의 행을 식별한 다음 새 결과 세트에 이름과 임시 변수를 제공하여 커서가 표시하는 행을 다음에 넣으십시오.
tempItem Item;
open allExpensiveItems for tempItem;
이 예제에서 tempItem은 데이터베이스의 ITEMS 테이블을 표시하는 SQLRecord 파트의 단일 레코드 변수입니다. for tempItem 코드는 EGL이 커서를 사용하여 한 번에 하나씩 이 레코드에 행을 이동하도록 지정합니다. open allExpensiveItems 코드는 결과 세트에 이름을 부여합니다. allExpensiveItems는 엄격히 말해서 변수가 아니라 ID입니다.
get 문과 같이 EGL은 open 문에서 SQL SELECT 문을 작성하여 명시적으로 만든 후 편집할 수 있습니다. 위의 open 문의 기본 SELECT 문 예제는 다음과 같습니다.
tempItem Item;

open expensiveItems for tempItem with
  #sql{
    select
      EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE, 
      EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
    from EGL.ITEM
    where
      EGL.ITEM.ITEM_ID >= :tempItem.ItemId
    order by
      EGL.ITEM.ITEM_ID asc
  };
이 기본 WHERE절은 각 항목의 ITEM_ID 값이 이전 값보다 커야함을 지정합니다(EGL은 SQL DECLARE CURSOR 및 OPEN CURSOR 문을 관리하며 명시적 SQL에 표시하지 않음).
결과 세트에 추가할 특정 행을 선택하려면 get 문을 사용하는 경우와 같이 WHERE절을 편집해야 합니다. 예를 들어, 주어진 변수보다 비용이 큰 항목만을 선택할 수 있습니다.
tempItem Item;
maxCost Price = 500;

open expensiveItems for tempItem with
  #sql{
    select
      EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE, 
      EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
    from EGL.ITEM
    where
      EGL.ITEM.PRICE >= :maxCost
    order by
      EGL.ITEM.ITEM_ID asc
  };
이제, expensiveItems 결과 세트에는 500으로 설정된 maxCost 변수 이상인 PRICE 열이 있는 데이터베이스의 모든 행이 포함됩니다.
이 행에 액세스하려면 루프의 코드 블록을 실행하여 결과 세트의 각 항목에 해당 코드를 적용하는 forEach 문을 사용하십시오. 루프의 각 반복 중에 EGL은 커서가 표시하는 행을 임시 변수로 이동시킨 다음 커서를 결과 세트의 다음 행으로 이동시킵니다. 예를 들어, 다음 코드는 가격이 500을 넘는 각 항목의 값을 인쇄합니다.
tempItem Item;
maxCost Price = 500;

open expensiveItems for tempItem with
  #sql{
    select
      EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE, 
      EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
    from EGL.ITEM
    where
      EGL.ITEM.PRICE >= :maxCost
    order by
      EGL.ITEM.ITEM_ID asc
  };
  
foreach (tempItem)
  SysLib.writeStdout(tempItem.Name :: " " ::
    tempItem.Description :: " $" :: tempItem.Price);
end
get next를 사용하여 수동으로 결과를 단계별로 이동할 수 있습니다. 이 경우, 예를 들어 결과 세트에 추가 결과가 있으면 0으로 설정되는 sysVar.sqlData.sqlcode의 값을 테스트하여 결과 세트에 추가 결과가 있는지를 발견해야 합니다.
tempItem Item;
maxCost Price = 500;

open expensiveItems for tempItem with
  #sql{
    select
      EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE, 
      EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
    from EGL.ITEM
    where
      EGL.ITEM.PRICE >= :maxCost
    order by
      EGL.ITEM.ITEM_ID asc
  };

// Retrieve the first row.
get next tempItem;

// As long as there are more rows,
// move the next row into the temporary variable
// and print its values. 
while (sysvar.sqlData.sqlcode == 0) 
  SysLib.writeStdout(tempItem.Name :: " " ::
    tempItem.Description :: " $" :: tempItem.Price);
  get next tempItem;
end
get 문에는 열기 커서 및 결과 세트와 함께 사용할 수 있는 기타 다양한 조작이 있습니다.
  • get next를 사용할 때 이전 예제에서처럼 임시 변수가 아니라 결과 세트를 지정할 수 있습니다. 예를 들어, get next from expensiveItems은 다음 행을 결과 세트에서 임시 변수로 이동합니다. 이 코드는 get next tempItem와 동등합니다. 마찬가지로, forEach 문에서 결과 세트 이름을 사용할 수 있습니다. forEach(from expensiveItems)forEach(tempItem)와 같습니다.
  • get current는 커서를 다음 행으로 이동하지 않고 현재 커서가 표시한 행을 검색합니다.
  • get firstget last는 결과에서 각각 첫 번째 행과 마지막 행을 검색합니다.
  • get previousget next의 반대로 커서 앞의 행을 검색합니다.
  • get absolute(position)는 결과 세트에서 특정 위치의 행을 검색합니다. 예를 들어, get absolute(5) tempItem은 결과 세트에서 다섯 번째 행을 검색하며 get absolute(-2) tempItem는 마지막에서 두 번째 행을 검색합니다.
  • get relative(position)는 커서의 현재 위치와 관련된 특정 위치의 행을 검색합니다. 예를 들어, get relative(3) tempItem은 현재 커서 위치 다음의 세 번째 행을 검색하며 get relative(-2) tempItem는 현재 커서 위치 앞의 두 번째 행을 검색합니다. get relative(0) tempItemget current tempItem과 동등합니다.
get next 이외의 해당 위치 관련 get 문을 사용하려면 시작부터 끝까지 한 번에 한 행씩 단계적으로 이동하지 말고 커서의 위치를 수동으로 변경하려 하는지 또는 결과 세트가 화면 이동 가능인지를 지정해야 합니다. 다음 예제에서와 같이 scroll 키워드를 open 문에 추가하십시오.
open expensiveItems scroll for tempItem;
여러 조건 중 임의의 조건(예: 커서가 결과 세트의 끝에 있으므로 결과를 리턴하지 않는 get next 문, 같은 결과 세트에 있는 다른 open 문 또는 프로그램의 끝)이 발생하면 EGL이 자동으로 커서를 닫습니다. 커서 및 결과 세트에 대한 작업을 완료하고 나면 다음 예에서와 같이 EGL close 문을 사용하여 닫을 수 있습니다.
close expensiveItems;
커서 및 결과 세트를 닫고 나면 커서에 의존하는 get next 및 기타 명령문은 더 이상 작동하지 않습니다.

단계적으로 결과 세트 이동

이 학습에서는 forEach 문을 사용하여 결과 세트를 단계적으로 이동하여 데이터베이스에서 특정 가격 이상의 항목을 검색할 것입니다.

  1. programs 패키지에 selectItems라는 새 프로그램을 작성하십시오.
  2. 프로그램에서 기본 코드를 제거하여 다음과 같이 표시되도록 하십시오.
    package programs;
    
    program selectItems type BasicProgram {}
      
      function main()
      end
      
    end
  3. 다음과 같이 데이터베이스에 액세스하는 동안 EGL에 발생할 수 있는 오류를 처리하는 함수를 추가하십시오.
    function handleDBException(exception SQLException)
      SysLib.writeStdout("Error accessing database. "::
        "See Troubleshooting section");
      SysLib.writeStdout(exception.message);
    end
    나중에 이 학습서에서 데이터베이스 액세스 시 발생하는 오류 처리에 대해 자세히 설명할 것입니다.
  4. 다음과 같이 최대 비용의 Price 매개변수를 기반으로 데이터베이스에서 행을 검색하는 함수를 추가하십시오.
    function printExpensiveItems(maxPrice Price in)
      
    end
    Price dataItem 파트는 DECIMAL 기본 유형에 따라 다릅니다. 이 유형은 eglderbyr7/ primitivetypes/data 파일에 정의되어 있습니다.
  5. 컨텐츠 지원을 사용하여 함수 선언에서 Price 매개변수를 추가하지 않은 경우 다음 import 문을 파일의 맨 위 package 문 바로 아래 추가하십시오.
    import eglderbyr7.primitivetypes.data.*;

    컨텐츠 지원을 사용하면 처음 몇 개의 문자를 입력한 다음 Ctrl+Space를 눌러 키워드 이름 및 유형을 완료할 수 있습니다. 컨텐츠 지원을 사용하여 유형(예: Price dataItem 파트)을 입력하면 컨텐츠 지원이 파일에 적절한 import 문을 추가합니다.

  6. 새 함수에서 open 문을 추가하여 결과 세트와 커서를 작성하십시오. 커서가 표시하는 행을 보유할 임시 Item 변수도 필요합니다.
      tempItem Item;
      open expensiveItems for tempItem;
  7. 다시 한 번, 컨텐츠 지원을 사용하여 Item 레코드 유형을 삽입하지 않은 경우 import 문을 추가하여 Record 파트를 범위 안에 가져오도록 하십시오.
    import eglderbyr7.data.Item;
  8. open 문에 커서를 두고 마우스 오른쪽 단추를 클릭한 다음 SQL 문 > 추가를 클릭하여 SQL 코드가 명시적으로 표시되도록 하십시오. open 문은 다음과 같습니다.
      open expensiveItems for tempItem with
        #sql{
          select
            EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE, 
            EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
          from EGL.ITEM
          where
            EGL.ITEM.ITEM_ID >= :tempItem.ItemId
          order by
            EGL.ITEM.ITEM_ID asc
        };
  9. 명시적 SQL 코드에서 WHERE절을 변경하여 maxPrice 변수 이상인 EGL.ITEM.PRICE 열 값이 함수에 전달된 행만을 선택하십시오.
      open expensiveItems for tempItem with
        #sql{
          select
            EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE, 
            EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
          from EGL.ITEM
          where
            EGL.ITEM.PRICE >= :maxPrice
          order by
            EGL.ITEM.ITEM_ID asc
        };
    maxPrice 변수 앞에 콜론을 포함하여 해당 변수가 SQL 키워드나 값이 아닌 EGL 변수임을 표시하십시오.
  10. 다음과 같이 open 문 다음에 항목에 대한 정보를 콘솔에 인쇄하는 forEach 루프를 추가하십시오.
      forEach (tempItem)
        SysLib.writeStdout(tempItem.Name :: " " ::
          tempItem.Description :: " $" :: tempItem.Price);
      end
    전체 함수는 다음과 같습니다.
    function printExpensiveItems(maxPrice Price in)
      
    tempItem Item;
    open expensiveItems for tempItem with
      #sql{
        select
          EGL.ITEM.ITEM_ID, EGL.ITEM.NAME, EGL.ITEM.IMAGE,
          EGL.ITEM.PRICE, EGL.ITEM.DESCRIPTION
        from EGL.ITEM
        where
          EGL.ITEM.PRICE >= :maxPrice
        order by
          EGL.ITEM.ITEM_ID asc
      };
      
    forEach (tempItem)
      SysLib.writeStdout(tempItem.Name :: " " ::
        tempItem.Description :: " $" :: tempItem.Price);
    end
  11. main 함수에서 함수를 호출하여 maxPrice 값을 전달하십시오.
    function main()
      try
        printExpensiveItems(200);
      onException(exception SQLException)
        handleDBException(exception);
      end
    end
  12. 프로그램을 생성하고 실행하십시오.
프로그램은 데이터베이스에서 판매 중인 항목 중에서 가격이 함수에 전달된 값 이상인 항목의 이름을 인쇄합니다. 예를 들어, 함수에 200을 전달하면 다음 결과가 발생합니다.
Laptop PC Great little machine.  Take it anywhere with you. $1111.11
Combination Safe Keep your valuables safe and secure.  Put 'em in here. $222.22
Desktop PC Lots'a power, at the right price.  Includes monitor. $888.55

selectItems.egl 파일의 전체 코드가 생성되었습니다. 파일에 빨간색 X 기호로 표시된 오류가 나타나면 코드가 학습 3에서 완성된 selectItems.egl 파일의 코드와 일치하는지 확인하십시오.

학습 체크포인트

이 학습에서는 openforEach를 사용하여 한 번에 한 행씩 결과 세트에 대해 작업하는 방법에 대해 배웠습니다.

커서를 사용하여 한 번에 한 행씩 결과 세트에 대한 작업을 수행하는 것이 get을 사용하여 전체 결과 목록을 레코드 배열로 검색하는 것보다 편리하고 효율적입니다.
자세한 정보는 openforEach의 도움말 항목을 참조하십시오.
< 이전 | 다음 >