3. 프로바이더 (Provider)

이제 구문에 대해서는 약간의 이해가 되어진 듯 하네여... 그렇다면 ASP를 통해서 이처럼 데이터 셰이핑을 하기위해선 그냥 단지 SQL문 대신에 셰이핑 언어를 사용하면 되는 것일까요? 다른 준비사항은 없는것일까요? 그럴 리가 있겠습니까? 당연히 특별한 지정이 필요합니다. 그것이 바로 프로바이더의 지정이지요.

이 데이터 셰이핑을 이용하기 위해서는 MSDataShape라는 데이터 공급자를 사용해야 합니다. 이를 지정하지 않고서는, 이를 통하지 않고서는 OLE BD로부터 가져온 데이터를 셰이핑할 방법은 없지요. 이 프로바이더는 ADO 2.0 이후로 지원되고 있고, 2000 서버에서는 이미 기본적으로 제공되어지고 있어요. 만일, Window NT에서 이를 사용하고 싶다면 다음 사이트에 가셔서 MDAC 최신 버전을 설치하시면 될 것임다.

http://www.microsoft.com/data/download.htm

데이터 셰이핑을 위해 제공되는 프로바이더인 MSDataShape는 이를 사용하기 위해서 소스레벨에서 다음과 같이 그 접속문자열을 작성할 수 있습니다.

strConnect = "Provider=MSDataShape; Data Provider=SQLOLEDB;"
strConnect = strConnect & "Data Source=데이터베이스서버_이름;"
strConnect = strConnect & "Initial Catalog=데이터베이스;"
strConnect = strConnect & "User id=sa; Password=;"

기존의 OLEDB를 통해서 데이터베이스에 접속하게 하는 문자열이

strConnect = "Provider=SQLOLEDB;"
strConnect = strConnect & "Data Source=데이터베이스서버_이름;"
strConnect = strConnect & "Initial Catalog=데이터베이스;"
strConnect = strConnect & "User id=sa; Password=;"

였던 것을 생각하면 아주 약간의 수정(굵은부분)으로 데이터 셰이핑을 위한 프로바이더를 지정할 수 있는 것을 볼 수 있을 것입니다. 단지 프로바이더가 MSDataShape로 바뀌고, 기존의 프로바이더는 Data Provider로 지정되어지는 것 정도이니까요.

저의 경운, 기존의 OLEDB용 접속문자열을 미리 만들어두고 사용하는 쪽에 속하기에  이 데이터 셰이핑을 위해서 프로바이더를 미리 따로 지정하는 방법을 사용하고는 한답니다. 다음처럼 말이지요.(Con은 ADO의 Connection객체 인스턴스입니다)

Con.Provider = "MSDataShape"
Con.open "Data " & StrConnect

이렇게 하게 되면 접속문자열에서 프로바이더를 지정할 필요가 없기에 단지 기본에 일반적으로 사용하던 접속문자열의 앞에 "Data "란 문자열을 붙여서 바로 이용할 수가 있으니 말입니다.

자. 이제 그럼 데이터 셰이핑을 위한 OLEDB 접속문자열도 알았으니 예제를 진행해 볼까요? 너무 오랫동안 뜸을 들여서 죄송스럽게 생각하고 있습니다만.. 이제야 시간이 되었네요...

4. 데이터 셰이핑. 그 첫 번째 예제

이제 대략적으로 데이터 셰이핑을 위한 준비는 되어진 것 같습니다. 그럼, 현재의 복잡한 머리를 정리하기 위해 가장 간단한 예제를 한번 해보기로 하시지요. 백견이 불여일타라 했습니다. 프로그래머는 100번의 설명보다는 한번의 코딩으로 이해한다.  그렇지 않은가여?   -_-;

DataShape1.asp

<% Option Explicit %>
<basefont size=2>
<%
' ***** 사용할 변수들의 선언부 *****
Dim Con
Dim Rs1, Rs2
Dim strConnect, Shape

' ADO 관련 객체의 생성
Set Con = Server.CreateObject("ADODB.Connection")

' 부모 레코드셋은 Rs1, 자식 레코드셋은 Rs2
Set Rs1 = Server.CreateObject("ADODB.RecordSet")
Set Rs2 = Server.CreateObject("ADODB.RecordSet")

'접속 문자열을 지정한다.
strConnect = "Provider=SQLOLEDB;"
strConnect = strConnect & "Data Source=여러분의 데이터베이스 서버의 이름;"
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 ({SELECT * FROM employee} "
Shape = Shape & " RELATE pub_id TO pub_id) as chEmp "

Rs1.ActiveConnection = Con
Rs1.Open Shape

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

     '******************** 자식 레코드셋 루프부분 시작 *******************
     set Rs2 = Rs1("chEmp").value< /p >

     Do until Rs2.EOF
          Response.Write "      "
          Response.Write "사원 : " & Rs2("fname") & " " & Rs2("lname") & "<br>"
          Rs2.MoveNext
     Loop
     Rs2.Close
     Set Rs2 = nothing
     '******************** 자식 레코드셋 루프부분 끝 *******************

     Rs1.MoveNext
Loop

Rs1.Close
Set Rs1 = nothing

Con.Close
Set Con = nothing
%>

자.. 이렇게 코딩하고 결과를 보면 결과화면은 어떻게 나오나요? 아마도 다음과 같이 나올 것입니다.

그러면 이제 소스를 한줄 한줄 차근히 풀어나가보도록 할까요?

앗.... 짜장면이 왔다.. 잠시만요.....  후루룩~ 쯔어업~~~   ...... 

그래서 말이죠...  어디까지 이야기했었죠?????   -_-a   아...  네...  그럼 소스를 보겠습니다.  *^-^*


① <% Option Explicit %>

먼저 설명할 것은 <% Option Explicit %> 부분입니다. 이 부분은 가급적이면 즐기면서 사용하기를 바래요.  이를 사용함으로써 소스내에서 사용하는 변수는 반드시 선언을 하고 사용해야만 하는 불편함(?)이 있지만, 변수 선언후 프로그래밍을 하는 것이 차후 프로그램이 복잡해질 경우에 유리하다함을 알게된다면 그 정도의 불편함은 감수할 수 있을 것이라고 생각한답니다.

언젠가는 다가올지 모르는, 디버깅으로 허송세월 보내는 것을 막아줄테니 말이죠. 복잡한 모듈을 만들다가 변수 때문에 크게 고생하신 분은 아마도 저의 말을 이해하실 겁니다. 이것은 마치 보험과 같은 코드라고 생각하지 않으세요?

② <basefont size=2>

이 태그는 사실 무의미한 편입니다. 단지 목적이 브라우저에 보여지는 글자들의 폰트 사이즈를 작게 지정하는 것이니 말입니다. 하지만, 기본 폰트는 글이 너무 커서 우리가 결과화면을 확인하는데 오히려 불편함을 느꼈습니다. 해서 이런 한 줄의 태그로 조금은 결과화면을 보기 편하게 한 것입니다.


Dim Con
Dim Rs1, Rs2
Dim strConnect, Shape

주석에 설명한대로 소스중에 사용할 변수들을 선언하는 부분이랍니다.


Set Con = Server.CreateObject("ADODB.Connection")
Set Rs1 = Server.CreateObject("ADODB.RecordSet")
Set Rs2 = Server.CreateObject("ADODB.RecordSet")

소스에서 사용할 ADO 관련 객체의 생성하는 부분입니다. 레코드셋 객체를 두 개나 설정한 것은 우리가 만들 계층형 레코드셋은 부모 레코드셋에서 자식 레코드 셋을 다시 연결하여 데이터를 가져올 것이므로, 자식 레코드셋을 위한 레코드셋이 필요한 이유이랍니다. 이 말이 어렵게 느껴진다면 먼저 소스 전체를 이해하도록 노력하세요.  전체를 이해하면 이 부분도 이해가 갈 것이라고 생각합니다.


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

'이미 여러차례 보아왔던 OLE DB를 통한 데이터 접속 문자열이다.
Con.Provider = "MSDataShape"
Con.Open "Data " & strconnect

Data Shaping를 위해서 프로바이더를 먼저 지정하고 Connection 객체를 통해서 데이터베이스 연결을 시도합니다. 저는 이 방법을 사용하지요. 물론, 프로바이더의 지정없이 그냥 접속문자열에 프로바이더를 추가해서 연결을 할 수도 있습니다. 그럴 경우는 접속문자열을 다음과 같이 바꾸어 접속해도 됩니다. 맘에 드는 방법을 사용하면 될 것이랍니다.

strConnect = "Provider=MSDataShape; Data Provider=SQLOLEDB;"
strConnect = strConnect & "Data Source=taeyo;"
strConnect = strConnect & "Initial Catalog=pubs;"
strConnect = strConnect & "User id=sa; Password=;"
Con.Open "Data " & strconnect


Shape = "SHAPE {SELECT * FROM Publishers} "
Shape = Shape & " APPEND ({SELECT * FROM employee} "
Shape = Shape & " RELATE pub_id TO pub_id) as chEmp "

데이터 셰이핑을 위한 문자열을 작성하는 부분입니다. 출판사의 모든 데이터를 가져오면서, 각 출판사에 근무하는 사원들의 명단도 같이 가져오기 위한 것으로 이미 위에서 셰이핑 언어의 예로 설명했던 구문입니다. 이 구문에 대해서는 아마도 어려움이 없을 것입니다.  조금은 말이지요..  ^_^;


Rs1.ActiveConnection = Con
Rs1.Open Shape

이제 셰이핑 언어에 따라 레코드셋을 오픈합니다. 이 부분의 소스가 낯설은 분은 아마도 다음 구문은 익숙할 것 같은데 어떠세요?

Rs1.Open Shape, Con

둘은 동일한 표현이지만, 단지 레코드셋의 커넥션객체와의 연결을 .ActiveConnection를 사용함으로써 먼저 지정한 것이랍니다.


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

이제부터 핵심의 시작인데요. 부모 레코드셋에서 Loop를 돌면서 각각의 출판사의 이름을 가져와서 문서에 출력해줍니다. 별일이 없다면 가장 먼저 "New Moon Books"이라는 출판사에서부터 시작할 겁니다.  Publishers 테이블에서 가져올 수 있는 출판사의 다른 정보들을 출력할 수 있지만, 여기서는 단지 출판사의 이름만을 출력해 보았답니다.

⑨ set Rs2 = Rs1("chEmp").value

부모 레코드셋에서 필요한 데이터를 모두 가져와서 출력했으므로 이제는 이 출판사와 관련된 자식 레코드셋의 데이터를 가져와서 뿌려주어야 합니다. 그것은 바로 사원들이죠. 이미 데이터 셰이핑을 통해서 현재의 레코드의 제일 마지막 컬럼은 자식 레코드셋으로 연결되어져 있습니다. 그 레코드셋을 연결해서 데이터를 가져와야 하는 것이죠.

데이터 셰이핑에 의해 만들어진 이 chEmp 컬럼은 그 진짜 모습은 레코드셋객체입니다. 고로 그냥은 이 레코드셋안의 데이터에 접근할 수 없어요. 해서 현재의 소스와 같은 부분이 필요한데요. chEmp컬럼안의 자식 레코드셋을 사용하기 위해서 그 컬럼의 값을 새로운 레코드셋 객체인 Rs2에 담는 것이지요. 그렇게 되면 이제 자식 레코드셋 객체의 데이터들(사원들의 정보들)은 Rs2라는 레코드셋을 통해서 접근이 가능해 지는 것입니다.


Do until Rs2.EOF
     Response.Write "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
     Response.Write "사원 : " & Rs2("fname") & "&nbsp;" & Rs2("lname") & "<br>"
     Rs2.MoveNext
Loop

자식 레코드셋내의 정보를 출력하기 위해서 루프를 돌면서 사원들의 이름을 가져와서 출력합니다. Response.Write "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" 부분은 보기 편하게 하기위해서 단지 들여쓰기를 위해서 지정한 것일뿐 대단한 의미는 없는 것입니다.


Rs2.Close
Set Rs2 = nothing

자식 레코드셋의 데이터를 다 출력해 주었으니 그 용도가 끝난 레코드셋을 닫고, 객체를 소멸시킵니다. 사용이 끝난 개체들의 빠른 자원반납은 퍼포먼스를 향상시키니 말입니다.


Rs1.MoveNext
Loop

이제 첫 번째 출판사에서 원하는 모든 데이터를 출력해 주었으니 다음 출판사로 넘어가게 합니다. 이 루프는 전체 출판사의 목록이 다 출력될 때까지 반복될 것이랍니다.


Rs1.Close
Set Rs1 = nothing
Con.Close
Set Con = nothing

모든 원하는 작업이 끝났으므로 부모 레코드셋과 데이터 커넥션 객체도 마저 소멸시킵니다.

훌룡합니다. 여러분은 제가 몇칠을 머리 아프게 고생한 것을 단 몇분만에 해결했습니다. 여러분의 프로그래머로서의 미래는 진짜로 밝을지도 모릅니다. (그럼 전??  T.T) 이제 자신감은 얻은 여러분은 필자가 내는 간단한 예제를 혼자의 힘으로 하실 수 있을 것입니다. 겁내지 마세요. 위의 예제와 다른 것이 거의 없습니다.

< 문제 >
Pubs 데이터베이스의 Employee 테이블에는 모든 사원의 목록이 담겨져 있습니다. 그러나, 각각의 사원들의 직분은 Jobs 테이블에 저장되어 있어요... 그렇다면, Employee 테이블에서 모든 사원들의 이름(fname, lname)을 출력하면서 동시에 각각의 사원이름 바로 밑에 그들의 직분(job_desc)을 표시하는 ASP 페이지를 그림과 같이 작성해 보시기 바란답니다. (물론, 데이터 셰이핑을 사용하여서 작성해야 하겠지요?) 

제가 작성한 소스는 다음 강좌에서 보여드리도록 하겠습니다.  ^^


'asp' 카테고리의 다른 글

구조화된 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
쿠키  (0) 2007.05.02

+ Recent posts