#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// EMPLOYEES 테이블 구조 기반으로 재정의
struct EMPLOYEE {
char emp_id[10]; // EMPL_ID
char full_name[30]; // FULL_NAME
char hire_date[15]; // HIRE_DATE
char married[5]; // MARRIED
char gender[5]; // GENDER
int on_leave; // 재직 상태(0: 재직 중, 1 : 휴직/퇴사)
};
typedef struct EMPLOYEE EMPLOYEE;
// 함수 프로토타입 (변동 없음)
int print_all_employees(EMPLOYEE* emp_list, int total_num_emp);
int print_employee_detail(EMPLOYEE* emp_list, int total_num_emp, char* target_id); // 💡 상세 조회 함수 수정
// 직원 정보 출력 헬퍼 함수 (변동 없음)
void display_employee_info(EMPLOYEE emp, int detail_mode);
// 문자열 비교 함수 (변동 없음)
char compare(char* str1, char* str2) {
while (*str1 && *str2) {
if (*str1 != *str2) {
return 0;
}
str1++;
str2++;
}
if (*str1 == '\\0' && *str2 == '\\0') return 1;
return 0;
}
// -------------------------------------------------------------
// * 직원 정보 출력 헬퍼 함수 구현 * (변동 없음)
// -------------------------------------------------------------
void display_employee_info(EMPLOYEE emp, int detail_mode) {
// ... (이전 코드와 동일)
if (detail_mode == 0) {
printf("%-10s // %-20s // %s\\n",
emp.emp_id, emp.full_name,
(emp.on_leave == 0) ? "재직 중" : "휴직/퇴사");
}
else {
printf("\\n--- 직원 상세 정보 ---\\n");
printf(" - 사번 (EMP_ID) : %s\\n", emp.emp_id);
printf(" - 이름 (FULL_NAME): %s\\n", emp.full_name);
printf(" - 입사일 (HIRE_DATE): %s\\n", emp.hire_date);
printf(" - 결혼 여부 : %s\\n", emp.married);
printf(" - 성별 (GENDER) : %s\\n", emp.gender);
printf(" - 재직 상태 : %s\\n", (emp.on_leave == 0) ? "재직 중" : "휴직/퇴사");
printf("----------------------\\n");
}
}
// -------------------------------------------------------------
// * 1. 전체 목록 조회 기능 구현 * (변동 없음)
// -------------------------------------------------------------
int print_all_employees(EMPLOYEE* emp_list, int total_num_emp) {
if (total_num_emp == 0) {
printf("등록된 직원 정보가 없습니다.\\n");
return 0;
}
printf("\\n============================================\\n");
printf(" ⭐ 전체 직원 목록 (간략 보기) ⭐\\n");
printf("============================================\\n");
printf("%-10s // %-20s // %s\\n", "사번", "이름", "상태");
printf("--------------------------------------------\\n");
for (int i = 0; i < total_num_emp; i++) {
display_employee_info(emp_list[i], 0);
}
printf("============================================\\n");
return 0;
}
// -------------------------------------------------------------
// * 2. 특정 사원 상세 정보 출력 기능 구현 (수정) *
// -------------------------------------------------------------
// 💡 함수 시그니처 수정: 사용자 입력을 main에서 받아와 바로 출력
int print_employee_detail(EMPLOYEE* emp_list, int total_num_emp, char* target_id) {
if (total_num_emp == 0) {
printf("등록된 직원 정보가 없습니다. \\n");
return 0;
}
printf("\\n--- 사번 %s 상세 정보 조회 ---\\n", target_id); // 💡 어떤 사번을 조회하는지 표시
for (int i = 0; i < total_num_emp; i++) {
if (compare(emp_list[i].emp_id, target_id)) {
display_employee_info(emp_list[i], 1);
return 0;
}
}
printf("\\n 사번 [%s]에 해당하는 직원을 찾을 수 없습니다.\\n", target_id);
return -1;
}
// -------------------------------------------------------------
// * Main 함수 (조회 기능 즉시 실행) *
// -------------------------------------------------------------
int main() {
int num_total_emp = 0;
int max_employees = 5;
EMPLOYEE* emp_list;
emp_list = (EMPLOYEE*)malloc(sizeof(EMPLOYEE) * max_employees);
if (emp_list == NULL) return 1;
// --- ⭐ 테스트를 위한 더미 데이터 등록 ⭐ --- (변동 없음)
strcpy(emp_list[0].emp_id, "A001");
strcpy(emp_list[0].full_name, "김철수");
strcpy(emp_list[0].hire_date, "2020-03-01");
strcpy(emp_list[0].married, "YES");
strcpy(emp_list[0].gender, "M");
emp_list[0].on_leave = 0;
num_total_emp++;
strcpy(emp_list[1].emp_id, "B007");
strcpy(emp_list[1].full_name, "이영희");
strcpy(emp_list[1].hire_date, "2022-09-15");
strcpy(emp_list[1].married, "NO");
strcpy(emp_list[1].gender, "W");
emp_list[1].on_leave = 1;
num_total_emp++;
// --------------------------------------------
// 💡 1. 전체 목록 조회 기능 실행
print_all_employees(emp_list, num_total_emp);
// 💡 2. 특정 사원 상세 정보 출력 기능 실행 (사번 'A001' 즉시 조회)
printf("\\n\\n--------------------------------------------\\n");
printf(" 🎯 특정 사원 정보 즉시 조회\\n");
print_employee_detail(emp_list, num_total_emp, "A001");
printf("--------------------------------------------\\n");
// 💡 3. 프로그램 종료
printf("\\n프로그램을 종료합니다.\\n");
free(emp_list);
return 0;
}
- 오후 5시 13분. 작업 중인 Pro C 코드. 지우기 전 기록 남기.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlca.h> // 💡 Pro*C: SQL 통신 영역 헤더
// -------------------------------------------------------------
// 💡 Pro*C: SQLCA (SQL Communication Area) 선언
// DB 작업 상태와 오류 정보를 담는 구조체입니다.
// -------------------------------------------------------------
EXEC SQL INCLUDE SQLCA;
// -------------------------------------------------------------
// 💡 Pro*C: Host Variable (C 변수) 선언 섹션
// SQL 문에서 사용할 C 변수와 구조체를 선언합니다.
// -------------------------------------------------------------
EXEC SQL BEGIN DECLARE SECTION;
// DB 연결 정보
char db_user[] = "scott";
char db_pass[] = "tiger";
char db_sid[] = "dev"; // 👈 DB 인스턴스 이름 (환경에 맞게 수정 필요)
// DB 테이블 구조체 (EMPLOYEES 테이블 컬럼 반영)
struct EMPLOYEE_T {
char emp_id[6]; // EMPL_ID (VARCHAR2(5) + NULL 종료 문자)
char full_name[31]; // FULL_NAME (VARCHAR2(30) + NULL 종료 문자)
char hire_date[9]; // HIRE_DATE (VARCHAR2(8) + NULL 종료 문자)
char married[2]; // MARRIED (VARCHAR2(1) + NULL 종료 문자)
int salary; // SALARY (NUMBER(10))
char gender[2]; // GENDER (VARCHAR2(1) + NULL 종료 문자)
};
typedef struct EMPLOYEE_T EMPLOYEE_T;
// 상세 조회 시 사용할 입력 변수
char search_id[6];
EXEC SQL END DECLARE SECTION;
// -------------------------------------------------------------
// * DB와 무관한 헬퍼 함수 정의 (Pro*C 파일에 포함) *
// -------------------------------------------------------------
// 직원 정보 출력 헬퍼 함수 (DB 구조체에 맞게 수정)
void display_employee_info(EMPLOYEE_T emp, int detail_mode) {
// DB 구조체에는 on_leave가 없으므로 재직 중으로 가정하고 출력
char on_leave_status[] = "Working";
if (detail_mode == 0) {
printf("%-10s // %-20s // %s\\n",
emp.emp_id, emp.full_name, on_leave_status);
}
else {
printf("\\n--- 직원 상세 정보 ---\\n");
printf(" - 사번 (EMP_ID) : %s\\n", emp.emp_id);
printf(" - 이름 (FULL_NAME) : %s\\n", emp.full_name);
printf(" - 입사일 (HIRE_DATE): %s\\n", emp.hire_date);
printf(" - 결혼 여부 : %s\\n", emp.married);
printf(" - 성별 (GENDER) : %s\\n", emp.gender);
printf(" - 연봉 (SALARY) : %d\\n", emp.salary); // 💡 SALARY 추가
printf(" - 재직 상태 : %s\\n", on_leave_status);
printf("----------------------\\n");
}
}
// -------------------------------------------------------------
// * 1. DB 연결/해제 함수 구현 *
// -------------------------------------------------------------
void connect_db() {
// SCOTT/TIGER@dev로 접속 시도
EXEC SQL CONNECT :db_user IDENTIFIED BY :db_pass USING :db_sid;
if (sqlca.sqlcode != 0) {
printf("🚨 DB 연결 실패 (SQLCODE: %d): %s\\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
exit(1);
} else {
printf("✅ DB 연결 성공: %s/%s@%s\\n", db_user, db_pass, db_sid);
}
}
void disconnect_db() {
EXEC SQL COMMIT WORK RELEASE; // 작업 확정 및 연결 해제
printf("DB 연결 해제 완료.\\n");
}
// -------------------------------------------------------------
// * 2. 전체 목록 조회 기능 구현 (DB 연결) *
// -------------------------------------------------------------
int print_all_employees() {
// 💡 커서 선언: DB에서 조회할 항목 지정
EXEC SQL DECLARE emp_cursor CURSOR FOR
SELECT EMPL_ID, FULL_NAME, HIRE_DATE, MARRIED, GENDER, SALARY
FROM EMPLOYEES
ORDER BY EMPL_ID;
EXEC SQL OPEN emp_cursor;
printf("\\n============================================\\n");
printf(" ⭐ DB에서 가져온 전체 직원 목록 ⭐\\n");
printf("============================================\\n");
printf("%-10s // %-20s // %s\\n", "사번", "이름", "상태");
printf("--------------------------------------------\\n");
EMPLOYEE_T current_emp; // 데이터를 담을 구조체
int found_count = 0;
while (1) {
// 💡 FETCH: 커서에서 데이터를 가져와 C 구조체 변수에 담습니다.
EXEC SQL FETCH emp_cursor INTO
:current_emp.emp_id, :current_emp.full_name, :current_emp.hire_date,
:current_emp.married, :current_emp.gender, :current_emp.salary;
if (sqlca.sqlcode == 1403) break; // 1403: Data Not Found (조회 완료)
if (sqlca.sqlcode != 0) {
printf("🚨 데이터 조회 오류 (SQLCODE: %d): %s\\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
break;
}
display_employee_info(current_emp, 0);
found_count++;
}
EXEC SQL CLOSE emp_cursor;
printf("============================================\\n");
printf("총 %d명의 직원을 DB에서 조회했습니다.\\n", found_count);
return 0;
}
// -------------------------------------------------------------
// * 3. 특정 사원 상세 정보 출력 기능 구현 (DB 연결) *
// -------------------------------------------------------------
int print_employee_detail() {
EMPLOYEE_T detail_emp; // 상세 정보를 담을 구조체
printf("조회할 사원의 사번(EMP_ID)을 입력하세요: ");
// 💡 사번을 C 변수에 입력받습니다.
scanf("%s", search_id);
// 💡 SELECT INTO: 단일 행 데이터를 조회할 때 사용
EXEC SQL SELECT EMPL_ID, FULL_NAME, HIRE_DATE, MARRIED, GENDER, SALARY
INTO :detail_emp.emp_id, :detail_emp.full_name, :detail_emp.hire_date,
:detail_emp.married, :detail_emp.gender, :detail_emp.salary
FROM EMPLOYEES
WHERE EMPL_ID = :search_id; // C 변수(:search_id)를 조건으로 사용
if (sqlca.sqlcode == 1403) {
printf("\\n ❌ 사번 [%s]에 해당하는 직원을 찾을 수 없습니다.\\n", search_id);
return -1;
} else if (sqlca.sqlcode != 0) {
printf("🚨 상세 조회 오류 (SQLCODE: %d): %s\\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return -1;
}
// 데이터가 성공적으로 조회되면 상세 정보 출력
display_employee_info(detail_emp, 1);
return 0;
}
// -------------------------------------------------------------
// * Main 함수 (DB 연결 및 조회 실행) *
// -------------------------------------------------------------
int main() {
connect_db(); // DB 연결
// 1. 전체 목록 조회 기능 실행 (DB에서 직접)
print_all_employees();
// 2. 특정 사원 상세 정보 출력 기능 실행 (DB에서 직접)
printf("\\n\\n--------------------------------------------\\n");
printf(" 🎯 특정 사원 정보 상세 조회\\n");
print_employee_detail();
printf("--------------------------------------------\\n");
disconnect_db(); // DB 연결 해제
return 0;
}