1. 연결
1. QSqlDatabase 객체 생성
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "EnrollConnection");
> driver : "QMYSQL", "QSQLITE", "QPSQL" 등
> connectionName : 여러 연결을 고려한 구분자(옵션, 없어도 됨)
2. 연결 정보 설정
// 예
db.setHostName("127.0.0.1"); // IP주소
db.setPort(3306); // 포트번호
db.setDatabaseName("your_database"); // DB이름
db.setUserName("root"); // ID
db.setPassword("1234"); // Password
3. 열기
if (!db.open()) {
qDebug() << "DB 열기 실패:" << db.lastError().text();
} else {
qDebug() << "DB 연결 성공!";
}
+) 이미 연결된 정보들이 있을 때
QString connName;
QSqlDatabase db;
if (QSqlDatabase::contains(connName)) {
db = QSqlDatabase::database(connName);
}
2. DB 쿼리 기본 사용법
0. DB 연결 확인
> 확실히 연결되었음을 인지하고 있다면 필요 없는 부분
if (!db.open()) {
setStatus("DB 연결 실패");
return false;
}
1. QSqlQuery 객체 생성
QSqlQuery query(db); // db는 사전에 연결해놓았던 QSqlDatabase 객체
2. 쿼리 실행
: .exec("SELECT ~ FROM ~")
2.1 즉시실행
if (!query.exec("SELECT user_id, user_name FROM face_images")) {
qDebug() << "쿼리 실패:" << query.lastError().text();
}
2.2 준비 후 바인딩
// 쿼리 준비(prepare)
query.prepare("INSERT INTO face_images(user_id, user_name, face_data) "
"VALUES(:id, :name, :data)");
// VALUES에 바인드(bindValue)
query.bindValue(":id", 1);
query.bindValue(":name", "홍길동");
query.bindValue(":data", QByteArray("...PNG BLOB..."));
// 쿼리 실행
if (!query.exec()) {
qDebug() << "삽입 실패:" << query.lastError().text();
}
3. 결과 읽기
: next() -> 한 행(row)씩 앞으로 이동
: value(i) / value("컬럼명") -> 현재 행 컬럼 값 반환
// 0번째 행(첫 행을 기준으로 while문 구조 설명)
while (query.next()) { // next()는 커서를 한 행씩 이동
int userId = query.value(0).toInt(); // 0번째 행의 첫번째 인덱스 값
QString userName = query.value("user_name").toString(); // 0번째 행의 user_name 컬럼의 값
QByteArray faceData = query.value("face_data").toByteArray(); // 0번째 행의 face_data 컬럼의 값
qDebug() << userId << userName;
}
> .next()는 커서를 한 행씩 이동시키고, 성공하면 True를, 실패하면 False를 반환함(결과적으로 더 이상 넘어갈 행이 없다면 while문은 자동으로 종료됨)
> value는 인덱스 형식으로도(value(0)), 컬럼명 형식으로도(value("user_name")) 사용 가능함
> .toInt() 나 .toString() 은 원하는 자료형 형태로 변환하기 위해 존재함.
3. 트랜잭션(두 개 이상의 쿼리를 실행)
> 예를 들어 main_db 라는 데이터베이스의 A 테이블에서 SELECT로 데이터를 읽고, B 테이블에 INSERT로 내용을 입력해야 할 로직이 있을 수 있다.
이 로직은 한 번에 수행되어야 하는데, 구체적으로 보면 A 테이블에서 제대로 읽지 못하고 B 테이블에 저장한다거나, 반대로 A 테이블에서는 제대로 읽었지만 B 테이블에는 잘못 입력이 되어버린다면 사용자의 의도와는 다른 문제가 발생된다.
따라서 두 개 이상의 쿼리문을 하나로 관리하여 한 쿼리문이라도 실패하면 전체적으로 실패를 반환하게 만드는 것이 필요하다.
// 1. 트랜잭션 시작
if (!db.transaction()) {
qDebug() << "트랜잭션 시작 실패:" << db.lastError().text();
return;
}
// 2. 쿼리 객체 생성
QSqlQuery q(db);
// 3. 성공 여부를 확인하기 위한 변수 생성
bool ok = true;
// 4. 첫번째 쿼리 실행
q.prepare("UPDATE users SET last_seen=NOW() WHERE id=:id");
q.bindValue(":id", 1001);
ok = ok && q.exec(); // true && true(q.exec()가 잘 수행되었다면 true를 반환하므로)
// 5. 두번째 쿼리 실행
q.prepare("INSERT INTO audit_log(user_id, action) VALUES(:id, 'update_last_seen')");
q.bindValue(":id", 1001);
ok = ok && q.exec(); // 위와 같음
6. 성공 여부에 따른 확정
if (ok) {
db.commit(); // 6.1 두 쿼리 모두 성공했으니 확정
} else {
db.rollback(); // 6.2 하나라도 실패 → 전부 취소
}
'FRAMEWORK > Qt' 카테고리의 다른 글
| <QT> CMake 캐시 초기화 (0) | 2025.08.16 |
|---|
