ODBC는 응용 프로그램과 DBMS간의 표준 인터페이스를 제공한다. 따라서 ODBC를 이용하는 응용 프로그램은 ODBC 드라이버를 제공하는 어떤 DBMS와도 연동할 수 있다. 즉, Oracle, MS SQL 무엇을 사용하든 상관없이 ODBC 드라이버만 제공하면 된다.
* DBMS : DataBase Management System
MFC는 ODBC를 이용한 데이터베이스 프로그래밍을 할 수 있도록 다음과 같은 클래스를 제공해준다.
CDatabase 클래스
데이터베이스와의 연결을 관리한다.
CRecordset 클래스
데이터의 추가, 삭제, 수정, 검색, 정렬 등에 관련된 기능이 있다.
* 참고. MS SQL ODBC 데이터 원본 추가 방법
1. ODBC 데이터 원본 관리자를 열고 [추가] 버튼을 클릭하여 DSN를 추가한다.
* DSN (Data Source Name)

2. SQL Server를 클릭하고 SQL Server를 선택 후 [마침] 버튼을 누른다.

3. DSN 이름과 서버 주소를 입력한다. [다음] 버튼을 클릭한다.
나는 내 PC에 설치했으므로 localhost (또는 127.0.0.1)로 설정했다.(\sqlexpress01은 sql 인스터스명)

4. 3번에서 입력한 SQL Server에 로그인 할 계정 정보를 입력한다. [다음] 버튼을 클릭한다.

5. 기본 데이터베이스를 선택한다. [다음] 버튼을 클릭한다.

6. [마침] 버튼을 클릭한다.

7. [데이터 원본 테스트] 버튼을 클릭하여 DB와의 연결을 확인한다. 정상적으로 연결됨을 확인하면 [확인] 버튼을 클릭하여 마무리한다.


8. ODBC 데이터 원본 관리자에 추가된 DSN을 확인할 수 있다.

Sample Program
* DB는 Microsoft SQL Server 2019 이용
* DB에 User (Name, Mobile, Birthday, Gender)라는 테이블을 생성하였음
* ODBCTest라는 이름의 MFC 프로젝트를 생성한 뒤 m_ctrlList 멤버 변수를 갖는 리스트컨트롤 추가하였음
1. include afxdb.h
ODBC를 사용하기 위해서는 stdafx.h 파일에 afxdb.h를 include 해줘야 한다.
// Stdafx.h
#include <afxdb.h> // ODBC
2. CDatabase, CRecordset 멤버변수 추가
// ODBCTestView.h
protected:
CDatabase m_db;
CRecordset *m_pRs;
3. 리스트컨트롤 칼럼 추가
void CODBCTestView::OnInitialUpdate()
{
// ...
// add list column
m_ctrlList.InsertColumn(0, "이름", LVCFMT_LEFT, 80);
m_ctrlList.InsertColumn(1, "전화번호", LVCFMT_LEFT, 150);
m_ctrlList.InsertColumn(2, "생일", LVCFMT_LEFT, 150);
m_ctrlList.InsertColumn(3, "성별", LVCFMT_LEFT, 80);
// ...
}
4. Select Sample
DB를 조회하여 레코드를 리스트컨트롤에 추가하는 예제이다.
void CODBCTestView::SelectData()
{
try
{
// DSN 정보를 이용하여 DB open
BOOL bOpen = m_db.OpenEx("DSN=DBTest;SERVER=localhost\\sqlexpress01;PORT=1433;UID=sa;PWD=1234;DATABASE=Test;");
if ( bOpen )
{
// recordset을 받아올 CRecordset 객체
m_pRs = new CRecordset( &m_db );
// query를 날려 recordset을 받아옴
BOOL bOpen = m_pRs->Open( CRecordset::snapshot, "SELECT Name, Mobile, Birthday, Gender FROM [User]" );
if ( bOpen )
{
CString strData;
int iRow = 1;
BOOL bIsEOF = m_pRs->IsEOF();
if ( !bIsEOF )
{
// MoveFirst() : 첫 번째 row로 이동
// IsEOF() : 현재가 마지막이면 1 리턴
// MoveNext() : 다음 row로 이동
for ( m_pRs->MoveFirst(); !m_pRs->IsEOF(); m_pRs->MoveNext() )
{
// 조회한 테이블의 칼럼 수
int iFieldCnt = m_pRs->GetODBCFieldCount();
for ( int iCol = 0; iCol < iFieldCnt; iCol++ )
{
// iCol번째의 필드 값을 읽어 strData에 넣어줌
m_pRs->GetFieldValue( iCol, strData );
// insert list control
if ( iCol == 0 )
m_ctrlList.InsertItem( iRow-1, strData );
else
m_ctrlList.SetItemText( iRow-1, iCol, strData );
}
iRow++;
}
}
}
else
{
AfxMessageBox("Query Fail..");
}
}
else
{
AfxMessageBox("DB Open Fail..");
}
}
catch ( CException *e )
{
e->ReportError();
}
// 사용 후 CRecordset, CDatabase 순으로 종료
if ( m_pRs->IsOpen() )
m_pRs->Close();
if ( m_db.IsOpen() )
m_db.Close();
}
* Snapshot : 현재 데이터베이스의 이용이 끝난 다음 갱신된 내용을 저장하는 것
* Dynaset : 갱신이 되는 순간 바로 수정을 하는 것
* 보통 ODBC는 Snapshot을 이용하고 DAO는 Dynaset을 이용한다. ODBC는 한 곳에서만 데이터베이스를 이용하는 것이 아니라 여러 곳에서 한 개의 데이터베이스를 읽고 수정하기 때문에 자신이 수정한 내용이 완벽할 경우에만 기록을 해야지 데이터를 잘못 기록하면 다른 곳에서 사용하다가 오류가 발생할 수 있기 때문이다. DAO는 개인 PC에서 단일적으로 사용하기 때문에 이런 오류가 없고 그렇기 때문에 바로바로 수정을 하는 방식을 택하게 된다.
5. Insert/Update/Delete Sample
Insert, Update, Delete는 ExecuteSQL() 함수를 이용한다. 내부 쿼리만 바꿔주면 된다.
void CODBCTestView::InsertData()
{
try
{
// DSN 정보를 이용하여 DB open
BOOL bOpen = m_db.OpenEx("DSN=DBTest;SERVER=localhost\\sqlexpress01;PORT=1433;UID=sa;PWD=kimgopa;DATABASE=Test;");
if ( bOpen )
{
try
{
m_db.ExecuteSQL("INSERT INTO [User] (Name, Mobile, Birthday, Gender) VALUES ('김고파', '010-2222-3333', '2020-12-03', 'f')");
}
catch ( CException *e )
{
e->ReportError();
}
}
else
{
AfxMessageBox("DB Open Fail..");
}
}
catch ( CException *e )
{
e->ReportError();
}
// 사용 후 CRecordset, CDatabase 순으로 종료
if ( m_pRs->IsOpen() )
m_pRs->Close();
if ( m_db.IsOpen() )
m_db.Close();
}
**
select 쿼리를 작성할 때 * (all)로 조회를 하면 나중에 테이블이 변경되었을 때 에러가 발생할 수 있다. 그러므로 필요한 칼럼만 select 해 오도록 하자.
'C, C++, MFC' 카테고리의 다른 글
| TCP/IP 프로그래밍 - 채팅 프로그램 (0) | 2021.01.06 |
|---|---|
| TCP/IP 프로그래밍 - 범용 소켓 클래스 (0) | 2020.12.31 |
| TCP/IP 프로그래밍 - 소켓 통신 (0) | 2020.12.19 |
| Visual Studio 2008 MFC 프로젝트 생성 (0) | 2020.11.30 |
| MFC란? (0) | 2020.11.28 |