mfc db 연결

유혜정·2022년 5월 3일
0

ms access 파일로 연결하기
ODBC 데이터 원본관리자(32비트)



고급설정도 진행하기

mfc 애플리케이션 옵션 설정
프로젝트 이름 : MFCODBC_EXAM

  • formview를 사용하는 이유: 대화상자를 만들어서 버튼을 만들기 위함

----framework.h

// odbc 관련된 헤더 파일
#include <afxdb.h>


32비트로 설정 (ms access만 해당)

----view.cpp

BOOL CMFCODBCEXAMView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: CREATESTRUCT cs를 수정하여 여기에서
	//  Window 클래스 또는 스타일을 수정합니다.

	return CFormView::PreCreateWindow(cs);
}

void CMFCODBCEXAMView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();

	/*
	1. db 연결
	2. sql 실행
	3. sql 결과 얻기
	4. 연결 종료

	CDatabase 클래스 : db 연결 관리하는 클래스
	CRecordset 클래스 : sql 구문을 실행하고 결과 집합을 관라하는 클래스
	*/

	//1. db 연결
	CDatabase db;
    BOOL bRet = db.OpenEx(_T("DSN=scott_db;uid=user1;PWD=passwd;"), 0);

	if (bRet) {
		AfxMessageBox(_T("DB 연결 성공"));
	}
	else {
		AfxMessageBox(_T("DB 연결 실패"));

	}
	//4. 연결 종료
	db.Close();
}

데이터 값 넣기
----view.cpp

void CMFCODBCEXAMView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();

	m_imageList.Create(48, 48, ILC_COLOR32, 5, 5);
	m_imageListSmall.Create(16, 16, ILC_COLOR32, 5, 5);

	m_imageList.Add(AfxGetApp()->LoadIcon(IDR_MAINFRAME));
	m_imageListSmall.Add(AfxGetApp()->LoadIcon(IDR_MAINFRAME));

	m_listView.SetImageList(&m_imageList, LVSIL_NORMAL);
	m_listView.SetImageList(&m_imageListSmall, LVSIL_SMALL);


	//칼럼 정보 출력
	m_listView.InsertColumn(0, _T("사원번호"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(1, _T("이름"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(2, _T("직업"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(3, _T("관리자"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(4, _T("입사일자"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(5, _T("급여"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(6, _T("상여금"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(7, _T("부서번호"), LVCFMT_LEFT, 100);

	DWORD dwExStyle = m_listView.GetExtendedStyle();
	m_listView.SetExtendedStyle(dwExStyle | LVS_EX_CHECKBOXES | LVS_EX_BORDERSELECT | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);



	/*
	1. db 연결
	2. sql 실행
	3. sql 결과 얻기
	4. 연결 종료

	CDatabase 클래스 : db 연결 관리하는 클래스
	CRecordset 클래스 : sql 구문을 실행하고 결과 집합을 관라하는 클래스
	*/

	//1. db 연결
	CDatabase db;
	BOOL bRet = db.OpenEx(_T("DSN=scott_db;uid=user1;PWD=passwd;"), 0);
	if (bRet) {
		//AfxMessageBox(_T("DB 연결 성공"));

		//2. sql 실행
		CRecordset rs(&db);
		rs.Open(CRecordset::forwardOnly, _T("select * from emp"));
		// rs에 데이터가 배열로 존재하게 됨
		
		//3. sql 결과 얻기
		int nRow = 0;
		CString strEmpNo;
		CString strEmpName;
		CString strEmpJob;
		while (!rs.IsEOF()) { // 마지막인지 확인
			rs.GetFieldValue((short)0, strEmpNo);
			rs.GetFieldValue((short)1, strEmpName);

			m_listView.InsertItem(nRow, strEmpNo, 0);
			m_listView.SetItemText(nRow++, 1, strEmpName);

			rs.MoveNext();
		}

	}
	else {
		AfxMessageBox(_T("DB 연결 실패"));
	}
	//4. 연결 종료
	db.Close();
}

데이터 값 전부 넣기

void CMFCODBCEXAMView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();

	m_imageList.Create(48, 48, ILC_COLOR32, 5, 5);
	m_imageListSmall.Create(16, 16, ILC_COLOR32, 5, 5);

	m_imageList.Add(AfxGetApp()->LoadIcon(IDR_MAINFRAME));
	m_imageListSmall.Add(AfxGetApp()->LoadIcon(IDR_MAINFRAME));

	m_listView.SetImageList(&m_imageList, LVSIL_NORMAL);
	m_listView.SetImageList(&m_imageListSmall, LVSIL_SMALL);


	//칼럼 정보 출력
	m_listView.InsertColumn(0, _T("사원번호"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(1, _T("이름"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(2, _T("직업"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(3, _T("관리자"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(4, _T("입사일자"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(5, _T("급여"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(6, _T("상여금"), LVCFMT_LEFT, 100);
	m_listView.InsertColumn(7, _T("부서번호"), LVCFMT_LEFT, 100);

	DWORD dwExStyle = m_listView.GetExtendedStyle();
	m_listView.SetExtendedStyle(dwExStyle | LVS_EX_CHECKBOXES | LVS_EX_BORDERSELECT | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);



	/*
	1. db 연결
	2. sql 실행
	3. sql 결과 얻기
	4. 연결 종료

	CDatabase 클래스 : db 연결 관리하는 클래스
	CRecordset 클래스 : sql 구문을 실행하고 결과 집합을 관라하는 클래스
	*/

	//1. db 연결
	CDatabase db;
	BOOL bRet = db.OpenEx(_T("DSN=scott_db;uid=user1;PWD=passwd;"), 0);
	if (bRet) {
		//AfxMessageBox(_T("DB 연결 성공"));

		//2. sql 실행
		CRecordset rs(&db);
		rs.Open(CRecordset::forwardOnly, _T("select * from emp"));
		// 형식 맞추기 (날짜, 상여금)
		//rs.Open(CRecordset::forwardOnly, _T("select				\
		empno, ename, job, mgr, to_char(hirdate, 'YYYY-MM-DD')		\
		hirdate, to_char(sal, '99,999') sal ,comm, deptno  from emp"));
		// 매니저 이름으로 바꾸기(없을경우는 null 표시)
		//rs.Open(CRecordset::forwardOnly, _T("select a.empno,						\
		a.ename, a.job, b.ename mgr_name, to_char(a.hirdate, 'YYYY-MM-DD') hirdate,	\
		to_char(a.sal, '99,999') sal , a.comm, a.deptno  from emp a, emp b			\
		where a.mgr = b.empno(+)"));
		// 부서명으로 출력하기
		//rs.Open(CRecordset::forwardOnly, _T("select		\
		a.empno, a.ename, a.job, b.ename mgr_name,			\
		to_char(a.hirdate, 'YYYY-MM-DD') hirdate,			\
		to_char(a.sal, '99,999') sal , a.comm, c.dname		\
		from emp a, emp b, dept c where a.mgr = b.empno(+)	\
		and a.depto = c.deptno(+)"));

		// rs에 데이터가 배열로 존재하게 됨
		
		//3. sql 결과 얻기
		int nRow = 0;
		CString strEmpNo;
		CString strEmpName;
		CString strEmpJob;
		CString strEmpMgr;
		CString strEmpDate;
		CString strEmpSal;
		CString strEmpComm;
		CString strEmpDeptno;

		while (!rs.IsEOF()) { // 마지막인지 확인
			rs.GetFieldValue((short)0, strEmpNo);
			rs.GetFieldValue((short)1, strEmpName);
			rs.GetFieldValue((short)2, strEmpJob);
			rs.GetFieldValue((short)3, strEmpMgr);
			rs.GetFieldValue((short)4, strEmpDate);
			rs.GetFieldValue((short)5, strEmpSal);
			rs.GetFieldValue((short)6, strEmpComm);
			rs.GetFieldValue((short)7, strEmpDeptno);

			m_listView.InsertItem(nRow, strEmpNo, 0);
			m_listView.SetItemText(nRow, 1, strEmpName);
			m_listView.SetItemText(nRow, 2, strEmpJob);
			m_listView.SetItemText(nRow, 3, strEmpMgr);
			m_listView.SetItemText(nRow, 4, strEmpDate);
			m_listView.SetItemText(nRow, 5, strEmpSal);
			m_listView.SetItemText(nRow, 6, strEmpComm);
			m_listView.SetItemText(nRow, 7, strEmpDeptno);

			nRow++;

			rs.MoveNext();
		}

	}
	else {
		AfxMessageBox(_T("DB 연결 실패"));
	}
	//4. 연결 종료
	db.Close();
}

삭제기능 추가

---view.cpp

void CMFCODBCEXAMView::OnBnClickedButton3()
{
	const int nCount = m_listView.GetItemCount();
	CString strEmpNo;
	CString strSQL;

	CDatabase db;
	BOOL bRet = db.OpenEx(_T("DSN=scott_db;uid=user1;PWD=passwd;"), 0);
	if (bRet) {

		for (int i = nCount - 1; i >= 0; --i) {
			if (m_listView.GetCheck(i)) {
				// 삭제할 사원 번호 얻음
				strEmpNo = m_listView.GetItemText(i, 0); //  사번이 나옴
				AfxMessageBox(strEmpNo);
				// 삭제할 사원 sql구문 생성
				strSQL.Format(_T("delete from emp where empno = %s"), strEmpNo);
				// 삭제 sql을 실행
				db.ExecuteSQL(strSQL); // ExecuteSQL : DML구문(insert, delete, update, merge)
				// 목록에서 제거
				m_listView.DeleteItem(i);
			}
		}
	}
	else {

	}
	db.Close();
}

한번에 쿼리 보내서 삭제하기

void CMFCODBCEXAMView::OnBnClickedButton3()
{
	const int nCount = m_listView.GetItemCount();
	CString strEmpNo;
	CString strSQL;

	CDatabase db;
	BOOL bRet = db.OpenEx(_T("DSN=scott_db;uid=user1;PWD=passwd;"), 0);
	if (bRet) {
    	// CStringArray : mfc에서 사용하는 vector 대용 자료형
		CStringArray arr;

		for (int i = nCount - 1; i >= 0; --i) {
			if (m_listView.GetCheck(i)) {
				//삭제할 사원 번호를 얻음
				strEmpNo = m_listView.GetItemText(i, 0); //  사번이 나옴
				//삭제할 사원번호를 배열에 추가
				arr.Add(strEmpNo);
				//목록에서 제거
				m_listView.DeleteItem(i);
			}
		}
		const int size = arr.GetSize();
		if (size != 0) {
			CString strInParam;
			for (int i = 0; i < size; i++) {
				strInParam += arr.GetAt(i) + _T(",");
                //strInParam += _T("'") + arr.GetAt(i) + _T("', "); // 문자열인 경우
			}
			strInParam.Delete(strInParam.GetLength() - 1, 1); // 마지막 ',' 지움
			
            // 삭제할 사원 sql구문 생성
            strSQL.Format(_T("delete from emp where empno in (%s)"), strInParam.GetBuffer());
			//삭제 SQL을 실행
			db.ExecuteSQL(strSQL);
            // ExecuteSQL : DML구문(insert, delete, update, merge)
		}
	}
	else {
		AfxMessageBox(_T("DB 연결 실패"));
	}
	//DB 연결 종료 
	db.Close();
}

예외처리 진행하기

void CMFCODBCEXAMView::OnBnClickedButton3()
{
	const int nCount = m_listView.GetItemCount();
	CString strEmpNo;
	CString strSQL;

	CDatabase db;
	BOOL bRet = db.OpenEx(_T("DSN=scott_db;uid=user1;PWD=passwd;"), 0);
	if (bRet) {
		CString strInParam;
		CArray<int, int> arr;

		// 삭제 위치와 삭제 사원번호만 얻음
		for (int i = nCount - 1; i >= 0; --i) {
			if (m_listView.GetCheck(i)) {
				// 삭제할 사원 번호 얻음
				strEmpNo = m_listView.GetItemText(i, 0);

				strInParam += strEmpNo + _T(", ");

				// 삭제할 사원의 위치를 배열에 추가
				arr.Add(i);
			}
		}
		const int size = arr.GetSize();
		try {

			if (!strInParam.IsEmpty()) {
				strInParam.Delete(strInParam.GetLength() - 1, 1);

				// 삭제할 사원 sql구문 생성
				strSQL.Format(_T("delete from emp where empno in (%s)"), strInParam.GetBuffer());
				//AfxMessageBox(strSQL);

				// 삭제 sql을 실행
				db.ExecuteSQL(strSQL);
				// ExecuteSQL : DML구문(insert, delete, update, merge)

				// 거꾸로 넣었으므로 순서대로 제거 실행
				for (int i = 0; i < arr.GetSize(); i++) {
					m_listView.DeleteItem(arr.GetAt(i));
				}
			}
		}
		catch (CException* p) {
			TCHAR szErr[100];
			p->GetErrorMessage(szErr, sizeof(szErr));
			AfxMessageBox(szErr);
		}
	}
	else {
		AfxMessageBox(_T("DB 연결 실패"));
	}
	db.Close();
}
profile
내가 시작한 공부, 공유할 코드

0개의 댓글