이전 강좌로 고민을 해보셨나요? 이전 강좌의 문제는 전 예제와 거의 같은 것이기에 조금만 집중하시면 그다지 어렵지 않게 풀 수 있을 겁입니다. 그래도.. 아직은 셰이프 구문에 자신이 없기에.. 문제는 셰이핑 문을 어떻게 만들어야 할 것인가? 이셨겠지요..  

사실 이것은 1 : 1 관계이기에 셰이핑이 필요없는 편에 속하기도 합니다. 하지만, 우리는 예를 들어 해보는 것이니 부디 무시하지 말고 같이 만들어 보기로 하자구요.  아마도 Shape를 위한 문자열은 다음과 같아야 할 것입니다.

SHAPE {SELECT job_id, fname, lname FROM Employee}
APPEND ({SELECT job_id, job_desc FROM jobs}
               RELATE job_id TO job_id) as chJob  

사실 정답(? 프로그램에 정답이란 것은 없을 것이지만)은 아닐 수도 있습니다만 저는 다음과 같이 구성했답니다.

<% Option Explicit %>
<basefont size=2>
<%
Dim Con
Dim RsEmp, RsJob
Dim strConnect, Shape

Set Con = Server.CreateObject("ADODB.Connection")
Set RsEmp = Server.CreateObject("ADODB.RecordSet")
Set RsJob = Server.CreateObject("ADODB.RecordSet")

strConnect = "Provider=SQLOLEDB;"
strConnect = strConnect & "Data Source=(local);"
strConnect = strConnect & "Initial Catalog=pubs;"
strConnect = strConnect & "User id=sa; Password=;"

Con.Provider = "MSDataShape"
Con.Open "Data " & strconnect

Shape =              " SHAPE {SELECT job_id, fname, lname FROM Employee} "
Shape = Shape & " APPEND ({SELECT job_id, job_desc FROM jobs} "
Shape = Shape & "                RELATE job_id TO job_id) as chJob "

RsEmp.ActiveConnection = Con
RsEmp.Open Shape

Do until RsEmp.EOF
     Response.Write "사원 : " & RsEmp("fname") & " " & RsEmp("lname") & "<br>"

     '******************** 자식 레코드셋 루프부분 시작 *******************
     set RsJob = RsEmp("chJob").value
     Do until RsJob.EOF
          Response.Write "    "
          Response.Write " - 직책: " & RsJob("job_desc") & "<br>"
          RsJob.MoveNext
     Loop

     RsJob.Close
     Set RsJob = nothing
     '******************** 자식 레코드셋 루프부분 끝 *******************

     RsEmp.MoveNext
Loop

RsEmp.Close
Set RsEmp = nothing

Con.Close
Set Con = nothing
%>

결과화면

어떤가요? 재미있지 않나요?아직 셰이핑의 진가는 전부 나오지 않았습니다. 현재까지 해 본 것은 가장 간단한 예만을 든 것입니다.그리고, 이 지금까지 해본 예제 들은 셰이프문을 쓰기보다는 그냥 쿼리로 돌리는 것이 사실 더 낫지요...  조금은 더 복잡한 경우에 그 때가 되어서야 셰이핑을 사용하는 것이 좋을 것입니다...

그렇다면 이제는 한번 서서히 깊게 들어가 보아야 하겠죠?


부모, 자식, 손자/손녀까지 계층적인 레코드셋

이번에는 한 단계를 더 들어가보도록 하겠슴다..  부모와 자식 레코드셋을 다루는 방법에 익숙해졌고, 어느정도는 데이터 셰이핑에 기본적인 자신감이 생겼으니 한 단계 더 하위인 손자/손녀 레코드셋까지 접근해보도록 하자구요.

뭔가 깊이 들어가는 기분에 알게 모르게 불안한 기운을 느끼실 수도 있겠습니다만, 이 단계까지만 적응하면 그 다음은 여러분이 얼마든지 스스로 공부하실 수 있을테니 조금만 더 집중했으면 합니다.....     ^____^_

우리는 위에서 부모와 자식 레코드셋, 그 계층적인 레코드셋을 다루는 것을 해보았습니다. 이번에는 부모와 자식, 그리고 또한 그의 자식까지 접근하여 데이터를 취합하는 것을 해보려 한답니다. 그림으로 설명하자면 다음과 같이 말이죠.


그림 : 계층적인 레코드셋 (부모,자식,손자/손녀)


그림 : 좀 더 구체적인 모습

이것을 셰이핑 언어로 작성하면 어떻게 될까요? 다음과 같이 될 것입니다.

SHAPE {SELECT * FROM Publishers} 
APPEND ( (SHAPE {SELECT * FROM Employee} 
                APPEND ({SELECT * FROM jobs}
                               RELATE job_id TO job_id) as chJob )  
                RELATE pub_id TO pub_id) as chEmp

아아.. 머리가 아픈가요? 아닙니다. 잘 살펴보면 어렵지 않아요. 일단 마음을 가라앉히고 함께 봐요. 위의 구문은 일단 머리속에서 지운 뒤 같이 차근히 만들어봅시다. 숨을 한번 크게 쉬고 말이죠.

계층적인 레코드셋을 만들 경운, 가급적 밑에서부터 올라가는 것이 좋아요. 그 편이 구성하기가 쉬우니 말이죠. 다시 말하면, 현재 우리가 작성할 것은 Publishers, Employee, Jods 3가지의 테이블이지만, 이를 한번에 생각하면 머리가 아프니 가장 밑의 단계인 자식 테이블과 손자/손녀 테이블을 먼저 셰이핑 언어로 만들어 보자는 것입니다. 이 부분은 이미 이전 예제에서 했던 부분이기도 하지요. 그렇다면 Employee와 Jobs를 계층적으로 만드는 셰이핑 언어는 어떻게 되었었나요? 다음과 같았었어요.  

SHAPE {SELECT * FROM Employee}
APPEND ({SELECT * FROM jobs}  
               RELATE (job_id TO job_id) as chJob  

기억나시죠? 이를 통해서 자식 테이블과, 손자/손녀 테이블은 셰이핑이 완료되었으며 이 자체가 하나의 통합된 자식 테이블이라고 볼 수 있을 것입니다. 다음 그림처럼 말이죠. 즉, 1단계 셰이핑을 통해서 만들어진 가칭 A 는 다음과 같다는 것입니다.

 

이제 남은 작업은 부모 테이블인 Publishers 와 자식 테이블 A(1단계 셰이핑을 통해 만들어진 테이블)을 셰이핑 하는 것입니다. 그렇다면 구문은 어떻게 될까요? 다음과 같아야 하지 않을까요?

SHAPE {SELECT * FROM Publishers}
APPEND (  ( A )
               RELATE pub_id TO pub_id) as chEmp

그렇습니다. 이렇게 되면 될 것입니다.  이것이 부모,자식, 손자 테이블이 모두 셰이핑되어서 완전한 계층이 이루어진 모습인 것이지요.  이제 A 대신에 그에 해당하는 구문을 넣어주면 다음과 같이 완성이 될 것입니다.

SHAPE {SELECT * FROM Publishers}
APPEND ( (SHAPE {SELECT * FROM Employee}
                APPEND ({SELECT * FROM jobs}
                               RELATE job_id TO job_id) as chJob )
                RELATE pub_id TO pub_id) as chEmp

막상 같이 구문을 작성하고 보니 그렇게 큰 어려움은 없었던 것 같네다. 다행입니다.  여러분의 내공은 이 순간에도 상승하고 있어요.  느끼실런지는 모르겠지만 말이죠~~~

자. 그럼 위의 구문을 이용해서 또 다른 예제를 한번 해보도록 하십시다... 이 예제 또한 가급적 여러분 스스로 먼저 만들어 볼 것을 권유해요. 이번의 예제의 내용은 이러합니다.

Pubs 데이터베이스의 Publishers 테이블에는 출판사들에 대한 정보가, Employee 테이블에는 모든 출판사 사원들의 목록이 담겨져 있구요. 그리고, 각각의 사원들의 직분은 Jobs 테이블에 저장되어 있습니다.  그렇다면, Publishers 테이블에 들어있는 각각의 출판사의 이름들을 출력하면서 동시에 각각의 출판사 이름 밑으로 그 출판사의 모든 사원들의 이름(fname, lname)을 출력하고 또한, 각각의 사원이름 바로 밑에 그들의 직분(job_desc)을 표시하는 페이지를 그림처럼 작성하는 것이죠. (단, 데이터 셰이핑을 사용하여서 작성해야 합니다.)

        
     
이렇게 하려면 어떻게 ASP 페이지를 만들면 될까요??? 저는 다음과 같이 구성해 보았습니다.

DataShape2_2.asp

<% Option Explicit %>
<basefont size=2>
<%
Dim Con
Dim Rspub, RsEmp, RsJob
Dim strConnect, Shape

Set Con = Server.CreateObject("ADODB.Connection")
Set Rspub = Server.CreateObject("ADODB.RecordSet")
Set RsEmp = Server.CreateObject("ADODB.RecordSet")
Set RsJob = Server.CreateObject("ADODB.RecordSet")

strConnect = "Provider=SQLOLEDB;"
strConnect = strConnect & "Data Source=taeyo;"
strConnect = strConnect & "Initial Catalog=pubs;"
strConnect = strConnect & "User id=sa; Password=;"

Con.Provider = "MSDataShape"
Con.Open "Data " & strconnect

Shape =              " SHAPE {SELECT * FROM Publishers} "
Shape = Shape & " APPEND ((SHAPE {SELECT * FROM Employee} "
Shape = Shape & "               APPEND ({SELECT * FROM jobs} "
Shape = Shape & "                             RELATE job_id TO job_id) as chJob)"
Shape = Shape & "               RELATE pub_id TO pub_id) as chEmp "

Rspub.ActiveConnection = Con
Rspub.Open Shape

Do until Rspub.EOF
     Response.Write "<h3>출판사명 : " & Rspub("pub_name") & "</h3>"

     set RsEmp = Rspub("chEmp").value

     Do until RsEmp.EOF
          Response.Write "      "
          Response.Write "사원 : " & RsEmp("fname") &  " " & RsEmp("fname") & <br>"

          '****************************************
          set RsJob = RsEmp("chJob").value
          Do until RsJob.EOF
               Response.Write "        "
               Response.Write " - 직책: " & RsJob("job_desc") & "<br>"
               RsJob.MoveNext
          Loop

          RsJob.Close
          Set RsJob = nothing
          '****************************************
     RsEmp.MoveNext
     Loop 

     RsEmp.Close
     Set RsEmp = nothing

Rspub.MoveNext
Loop

Con.Close
Set Con = nothing
%>

소스를 바라보며 최대한 스스로 이해하려고 노력해 보세요. 기존의 소스에서 조금은 확장된 모습이기에 주의깊게 바라보면 이해가 가능할 것입니다. 이전 예제와 동일한 부분은 설명을 생략하고 이번 예제에서 추가된 부분만을 위주로 소스를 설명하도록 하겠습니다.


Set Rspub = Server.CreateObject("ADODB.RecordSet")
Set RsEmp = Server.CreateObject("ADODB.RecordSet")
Set RsJob = Server.CreateObject("ADODB.RecordSet")

이번에는 총 3단계의 계층이기에 그에 맞게 3개의 레코드셋 객체가 필요할 것입니다. 각각의 이름도 테이블과 연관하여 RsPub, RsEmp등을 주어 직관력을 높이도록 해 보았습니다.


Shape =              " SHAPE {SELECT * FROM Publishers} "
Shape = Shape & " APPEND ((SHAPE {SELECT * FROM Employee} "
Shape = Shape & "               APPEND ({SELECT * FROM jobs} "
Shape = Shape & "                             RELATE job_id TO job_id) as chJob)"
Shape = Shape & "               RELATE pub_id TO pub_id) as chEmp "

우리가 이미 만들어 본 셰이핑 구문입니다. 이전 강좌에서 말이지요... 이를 그대로 사용하도록 하겠습니다.


Do until Rspub.EOF
Response.Write "<h3>출판사명 : " & Rspub("pub_name") & "</h3>"
set RsEmp = Rspub("chEmp").value

이제 루프가 시작됩니다. 먼저 출판사의 이름을 화면에 출력해주고 있는 것을 볼 수 있지요. 우리가 Publishers 테이블에서 필요한 것은 단지 출판사의 이름이었기에, 그 이름만을 출력해주고, publishers 테이블에 새로 생긴 chEmp컬럼에서 참조 가능한 자식 테이블로의 접근을 시도합니다.

set RsEmp = Rspub("chEmp").value 란 코드를 통해서 자식 레코드셋을 RsEmp란 레코드셋 객체에 설정하고 있는 것을 볼 수 있지요. 이제 RsEmp 레코드셋을 통해서 자식 레코드셋의 데이터들을 접근할 수 있습니다. 즉, Employee 테이블의 데이터들을 접근 할 수 있는 것이랍니다...


Do until RsEmp.EOF
Response.Write "      "
Response.Write "사원 : " & RsEmp("fname") & " " & RsEmp("fname") & "<br>"

'****************************************
set RsJob = RsEmp("chJob").value

자식 레코드셋의 루프가 시작됩니다. Employee 테이블에서 필요한 정보를 모두 출력한 뒤, 손자/손녀 레코드 셋의 데이터에 접근하기 위해서 set RsJob = RsEmp("chJob").value을 통해 손자/손녀 레코드셋을 RsEmp란 레코드셋 객체에 설정하고있는 것을 볼 수 있습니다.

이제 RsJob 레코드셋을 통해서 자식 레코드셋의 데이터들을 접근할 수 있어요. 즉, Jobs 테이블의 데이터들을 접근 할 수 있는 것이랍니다.

그 이후의 코드는 레코드셋 객체를 소멸하고 페이지를 정리하는 코드이기에 자세한 설명은 필요없어 보이네요.

저의 이 예제에 대한 설명이 어렵게 느껴지실 수도 있을지도 모르겠네요.... 최대한 쉽게 설명하려 노력했지만 간혹 그러한 설명이 오히려 역효과를 낼 수도 있더라구요. 이해가 안가면 다른 서적을 참고해서라도 가급적 이해하시려 노력하세요.

제 자그마한 강좌가 모든 것을 해결해 줄 수는 없겠지요?. 데이터 셰이핑 조금만 노력한다면 무척이나 재미있는 것인데...  안타깝지만, 사정에 의해서... 셰이핑에 대한 강좌는 이쯤에서 정리해야 할 것 같습니다...  반응들도 거의 없고...  나름대로의 사정도 좀 있구요  ^^

하지만, 셰이핑에 대해서 제 책인 Taeyo's Advanced ASP 에서는 이 강좌내용에다가 조금 더 다루어 놓았거든요. 이 강좌는 책에 쓴 부분의 절반정도라고 보시면 될 것 같아요.. 그렇다고 책을 사실 필요는 없구요... 서점에 가셔서 이후 부분을 읽어보시기만 하세요..  소스는 제 사이트에서 다운로드가 가능하니까요..  ^^  그럼 저렴하게... 투자해서 공부를 하실 수가 있답니다.

더 깊게 다루고 싶었지만..  그렇게 하지 못한 점 대단히 죄송스럽게 생각하구요... 다음에 또 기회가 된다면.. 조금은 더 다루어 보기로 하겠습니다.. 파이팅입니다.

'asp' 카테고리의 다른 글

Global.asa와 사이트 카운터  (0) 2007.05.02
구조화된 Stored Procedure 사용법  (0) 2007.05.02
ActiveX Data Object 2.5 and over  (0) 2007.05.02
ActiveX Data Object 2.5 and over  (0) 2007.05.02
ASP에서 성능문제 향상방법  (0) 2007.05.02

+ Recent posts