지금까지는 각 데이터 액세스 함수가 오직 한 테이블에서만
행을 검색했습니다. 이 학습에서는 EGL과 SQL 테이블 결합을 사용하여
한 번에 여러 테이블에 대한 작업을 수행하는 방법을 설명합니다.
SQL 테이블 결합에 대한 전체 설명은 이 학습서의 범위를
벗어납니다. 쉽게 말해서, 테이블 결합은 둘 이상의 관련된 테이블로부터
결과 세트를 조합합니다.
예를 들어, 데이터베이스의
CUSTOMERS 테이블은 고객의 성 및 이름과, 1차 키로서 ID 번호를 포함합니다(기타
여러 콜론 포함).
표 1. CUSTOMER 테이블의
샘플 데이터| CUSTOMER_ID |
FIRST_NAME |
LAST_NAME |
| 1 |
Fred |
Filibuster |
| 2 |
Andy |
Lundquist |
| 3 |
Billie |
Kingman |
ORDERS 테이블에는 1차 키로서 주문 ID 번호와
주문 양을 포함합니다. 테이블에는 주문을 한 고객의 ID 번호도
포함되며 해당 열은
외부 키가 됩니다.
표 2. ORDERS 테이블의 샘플 데이터| ORDER_ID |
CUSTOMER_ID |
ORDER_AMOUNT |
| 1 |
1 |
111.11 |
| 2 |
1 |
222.22 |
| 3 |
1 |
333.33 |
이 경우,
CUSTOMER_ID 열이 두 테이블 사이의 관계를 작성하므로 이 열은
테이블 결합에 사용할 좋은 후보입니다. 이 학습에서는
이 두 테이블을 사용자 정의된 SQLRecord 파트와 결합하여 고객의 주문과
해당 고객을 일치시키는 결과 세트를 생성합니다.
테이블 결합은
복잡한 데이터베이스 오퍼레이션이므로 데이터베이스의 동작에 대해
잘 이해하고 있어야 하며 출력을 주의하여 테스트해야 합니다. 이 학습에서
표시되는 바와 같이 예상 데이터를 항상 얻지는 못합니다.
- 다음과 같이 새 SQLRecord 파트를 보유할 새 EGL 소스 파일을 작성하십시오.
- 프로젝트 탐색기 보기에서 EGLSQL 프로젝트를 마우스 오른쪽 단추로
클릭한 다음 을 클릭하십시오.
- 새 EGL 소스 파일 창에서 패키지 필드에
data라는 이름을 입력하십시오.
- EGL 소스 파일 이름 필드에 records를 입력하십시오.
- 완료를 클릭하십시오.
새 EGL 소스 파일이 작성되어 편집기에서 열립니다.
- 새 파일에서 package 문 아래
새 SQLRecord의 이름을 입력하여 CUSTOMER와 ORDERS 테이블을
결합하십시오.
record OrderCustomerJoin type SQLRecord
{tableNames = [["EGL.CUSTOMER", "C"], ["EGL.ORDERS", "O"]]}
end
이 레코드의 첫 번째 행은 기타 SQLRecord 파트와 동일합니다.
레코드의 이름과 SQLRecord 스테레오타입을 지정합니다. 두 번째 행은
이 레코드가 연관될 테이블을 tableNames
특성 값으로 지정합니다. 이전 학습에서 작업한
단일 테이블 레코드는 이 특성에서 한 테이블만 나열합니다(예: Orders 레코드의
ORDERS 테이블).
record Orders type sqlRecord {
tablenames=[["EGL.ORDERS"]]
...
작성 중인 OrderCustomerJoin 레코드는
두 테이블 모두에서 데이터를 검색하도록 tableNames 특성에
두 테이블을 나열해야 합니다. 구분을 쉽게 하기 위해 레코드는 각 테이블 이름의
별명을 포함합니다(ORDERS의 경우 "O" 및 CUSTOMERS의 경우 "C"). 이러한 별명을 통해
레코드에서 테이블 이름을 보다 쉽게 참조할 수 있습니다.
이제,
레코드 파트의 기본 정보를 지정했으므로 EGL이 나머지 파트를
채울 수 있습니다. 그러나, 우선 EGL이 연결 정보를 검색할 데이터베이스를
지정해야 합니다.
- 다음과 같이 EGL의 기본 SQL 데이터베이스로 Derby 데이터베이스를 설정하십시오.
- 을 클릭하십시오.
- 환경 설정 창에서 EGL을 펼치고
SQL 데이터베이스 연결을 클릭하십시오.
- 연결 목록에서 EGLDerbyR7 또는 EGLDerbyR71이라는
데이터베이스 연결을 선택하십시오.
- 확인을 클릭하십시오.
- 다시 records.egl 파일에서 커서를 레코드의 이름에
두십시오.
- OrderCustomerJoin 레코드의 이름에 커서를 둔 상태로
마우스 오른쪽 단추를 클릭한 다음 을 클릭하십시오. EGL SQL 검색 기능
- 암호 프롬프트에서 사용자 이름 및 암호의 기본값을 그대로
두십시오. 샘플 데이터베이스에는 특정 사용자 이름이나 암호가 필요하지
않습니다. EGL SQL 검색 기능이
keyItems 특성과 테이블의 행 필드를 포함하여
나머지 SQLRecord 파트를 작성합니다.
record OrderCustomerJoin type SQLRecord
{tableNames = [["EGL.CUSTOMER", "C"], ["EGL.ORDERS", "O"]],
keyItems=[CUSTOMER_ID, ORDER_ID]}
CUSTOMER_ID int
{column="C.CUSTOMER_ID", isReadOnly=yes};
FIRST_NAME string
{column="C.FIRST_NAME", isReadOnly=yes,
isSqlNullable=yes, sqlVariableLen=yes, maxLen=30};
LAST_NAME string
{column="C.LAST_NAME", isReadOnly=yes,
isSqlNullable=yes, sqlVariableLen=yes, maxLen=30};
...
ORDER_ID int
{column="O.ORDER_ID", isReadOnly=yes};
orders_CUSTOMER_ID int
{column="O.CUSTOMER_ID", isReadOnly=yes,
isSqlNullable=yes};
ORDER_AMOUNT decimal(8,2)
{column="O.ORDER_AMOUNT", isReadOnly=yes,
isSqlNullable=yes};
ORDER_DETAILS string
{column="O.ORDER_DETAILS", isReadOnly=yes,
isSqlNullable=yes, sqlVariableLen=yes, maxLen=111};
end
각 필드의 열 특성 값은
tableNames 특성에 지정된 대로 테이블의 별명으로 시작됩니다.
이 별명을 사용하여 특정 필드가 연관되는 테이블을 추적할 수
있습니다.
- records.egl 파일을 저장하되 닫지는 마십시오.
- printCustomerOrders라는 프로그램 패키지에서 새 프로그램 파트를 작성하십시오.
- 새 프로그램에서 기본 코드를 제거하십시오.
- 프로그램의 main 함수에서 사용자가 방금 작성한 OrderCustomerJoin 레코드를 기반으로
배열 변수를 작성하십시오.
allCustomerOrders OrderCustomerJoin[0];
Ctrl+Space를
눌러 레코드 파트 유형을 삽입하도록 컨텐츠 지원을 사용하십시오.
컨텐츠 지원을 사용하지 않는 경우 import 문을
파일의 맨 위 package문 바로 아래에 수동으로 추가해야 합니다.
import data.OrderCustomerJoin;
- open 및 forEach 문을 사용하여
데이터베이스에서 행을 검색하고 콘솔에 값을 인쇄하십시오.
tempRec OrderCustomerJoin;
open resultSet for tempRec;
forEach (tempRec)
SysLib.writeStdout(tempRec.CUSTOMER_ID :: " " ::
tempRec.LAST_NAME :: " " :: tempRec.ORDER_ID);
end
- 프로그램을 저장하고 생성하여 실행하십시오. 사용자가 테이블 결합의 함정을
잘 이해하고 있다면, 이 테이블 결합의 오류와 출력이 그리 유용하지 않다는 것을
알아챘을 것입니다.
1 Filibuster 1
1 Filibuster 2
1 Filibuster 3
...
1 Filibuster 22
1 Filibuster 23
2 Lundquist 1
2 Lundquist 2
2 Lundquist 3
2 Lundquist 4
...
2 Lundquist 22
2 Lundquist 23
3 Kingman 1
3 Kingman 2
...
데이터베이스가 테이블 사이의 논리적 교차 참조를
작성하지 않았습니다. 그 대신, 가능한 모든 조합으로 CUSTOMERS 테이블의 각 행을
ORDERS 테이블의 각 행과 쌍으로 연결합니다. 이 결과에서 각 고객은
모두를 주문한 것으로 기록되며, 이 기록은 올바르지 않습니다.
open 문 뒤에서 SQL 코드를 명시적으로 표시되게
만들면 SQL이 WHERE절을 사용하지 않고 두 테이블 모두에서 모든 행을 선택하는
것을 확인할 수 있습니다.
open resultSet for tempRec with
#sql{
select
C.CUSTOMER_ID, C.FIRST_NAME, C.LAST_NAME, C.PASSWORD,
C.PHONE, C.EMAIL_ADDRESS, C.STREET, C.APARTMENT,
C.CITY, C.STATE, C.POSTALCODE, C.DIRECTIONS,
O.ORDER_ID, O.CUSTOMER_ID, O.ORDER_AMOUNT,
O.ORDER_DETAILS, O.ORDER_DATE, O.ORDER_STATUS
from EGL.CUSTOMER C, EGL.ORDERS O
order by
C.CUSTOMER_ID, O.ORDER_ID asc
};
테이블을 효과적으로 결합하려면 테이블 유니온을 리턴하지 않고
테이블을 논리적으로 병합하는 방법을 데이터베이스에 알려야 합니다.
명시적 SQL 코드를 편집하여 이 작업을 수행할 수 있지만, 이 경우
레코드를 사용할 때마다 작업을 수행하거나 정확하지 않은 데이터를 검색할 수도 있다는
위험이 있습니다. 대신, 내재적 SQL 코드가 항상 효과적인 테이블
결합을 수행하도록 이 레코드의 기본 선택 조건을 설정합니다.
- open 문 뒤에서 SQL 코드를 명시적으로 만든 경우
레코드 이름에 커서를 두고 마우스 오른쪽 단추로 클릭한 다음 를
클릭하여 다시 내재적으로 만드십시오.
- records.egl 파일의 레코드 파트 정의로 되돌아가십시오.
- 다음과 같이 레코드 파트 정의에 defaultSelectCondition 특성을
추가하십시오.
record OrderCustomerJoin type SQLRecord
{tableNames = [["EGL.CUSTOMER", "C"], ["EGL.ORDERS", "O"]],
keyItems=[CUSTOMER_ID, ORDER_ID],
defaultSelectCondition = #sqlCondition{ condition }}
defaultSelectCondition 특성은
이 레코드와 get 또는 open을
사용할 때 내재적 SQL 코드와 기본 명시적 SQL 코드에 WHERE절을
지정합니다.
- #sqlCondition{} 블록에서
기본 "condition" 텍스트를 바꾸고 이 두 테이블 사이의
SQL 테이블 결합에 올바른 WHERE절을 입력하여 전체 테이블 이름이 아니라
테이블 별명을 사용하도록 하십시오.
defaultSelectCondition = #sqlCondition{ O.CUSTOMER_ID = C.CUSTOMER_ID }}
키워드
WHERE를 추가할 필요가 없습니다. 이 경우에는 EGL이 WHERE를 SQL 코드에
자동으로 삽입합니다.
- 파일을 저장하십시오. 이제, open 문 뒤에서
SQL 코드를 명시적으로 만든 경우 다음과 같이 표시됩니다.
open resultSet for tempRec with
#sql{
select
C.CUSTOMER_ID, C.FIRST_NAME, C.LAST_NAME, C.PASSWORD,
C.PHONE, C.EMAIL_ADDRESS, C.STREET, C.APARTMENT,
C.CITY, C.STATE, C.POSTALCODE, C.DIRECTIONS,
O.ORDER_ID, O.CUSTOMER_ID, O.ORDER_AMOUNT,
O.ORDER_DETAILS, O.ORDER_DATE, O.ORDER_STATUS
from EGL.CUSTOMER C, EGL.ORDERS O
where
O.CUSTOMER_ID = C.CUSTOMER_ID
order by
C.CUSTOMER_ID, O.ORDER_ID asc
};
이제, SQL 코드는 리턴된 행을 CUSTOMER 및 ORDERS 테이블 모두에
같은 고객 번호가 있는 행으로만 제한하는 WHERE절을
포함합니다.
- 프로그램을 저장하고 생성하여 실행하십시오.
효과적으로 테이블을 결합하면
이 프로그램의 결과는 각각의 주문을 한 고객을 표시합니다.
1 Filibuster 1
1 Filibuster 2
1 Filibuster 3
...
1 Filibuster 11
1 Filibuster 18
2 Lundquist 7
2 Lundquist 8
2 Lundquist 12
2 Lundquist 15
2 Lundquist 20
3 Kingman 13
4 Liebowitz 14
6 Springsteen 22
7 St. Louis 16
8 Sharov 17
9 Hudak 23
이 학습에서 사용하는 두 파일의 전체 코드를 살펴보십시오. 파일에 빨간색 X 기호로
표시된 오류가 나타나면 사용자의 코드가 학습 5에서 완성된 printCustomerOrders.egl 및 records.egl 파일의 코드와 일치하는지 확인하십시오.