Qtの基礎 - データベース

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
2024年8月14日 (水) 08:00時点におけるWiki (トーク | 投稿記録)による版 (→‎SQLite3)
ナビゲーションに移動 検索に移動

概要



MariaDB

以下の例では、MariaDBのデータベースを使用して、以下に示すようなテーブルを作成して基本的なCRUD操作を行っている。
実務では、必要に応じてフィールドを追加、または、データ型や制約を調整したりする必要がある。

  • テーブル名
    people
  • id
    INT型
    制約 1 : AUTO_INCREMENT
    制約 2 : PRIMARY KEY
    各レコードを一意に識別するための自動増分の主キー。
  • name
    VARCHAR(40)型
    制約 : NOT NULL
    名前を格納するフィールドで、最大40文字まで保存可能。
  • age
    INT型
    年齢を格納する整数型のフィールド。


また、使用時にはエラーハンドリングおよびセキュリティ対策 (SQLインジェクション対策等) を適切に実装することを推奨する。

 # CMakeLists.txtファイル
 
 cmake_minimum_required(VERSION 3.21)
 
 project(QtMariaDBProject LANGUAGES CXX)
 
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 set(CMAKE_AUTOUIC ON)
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTORCC ON)

 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Sql)
 find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Sql)
 
 # MariaDB Connector/Cを検索
 find_path(MARIADB_INCLUDE_DIR mysql.h
    /usr/include/mysql
 )
 
 find_library(MARIADB_LIBRARY NAMES mariadb
    PATHS
    /usr/lib
    /usr/lib64
 )
 
 if(NOT MARIADB_INCLUDE_DIR OR NOT MARIADB_LIBRARY)
    message(FATAL_ERROR "MariaDB Connector/C not found!")
 endif()
 
 add_executable(QtMariaDBProject
    main.cpp
    DataBaseManager.h
    DataBaseManager.cpp
 )
 
 # QtライブラリとMariaDBライブラリをリンク
 target_link_libraries(QtMariaDBProject PRIVATE 
    Qt${QT_VERSION_MAJOR}::Core
    Qt${QT_VERSION_MAJOR}::Sql
    ${MARIADB_LIBRARY}
 )
 
 # MariaDBのヘッダファイルのディレクトリを追加
 target_include_directories(QtMariaDBProject PRIVATE
    ${MARIADB_INCLUDE_DIR}
 )


 // DataBaseManager.hファイル
 
 #include <QtSql>
 #include <QDebug>
 
 class DatabaseManager
 {
 public:
    DatabaseManager();
    ~DatabaseManager();
 
    bool openConnection();
    void closeConnection();
    bool createTable();
    bool insertRecord(const QString &name, int age);
    bool updateRecord(int id, const QString &name, int age);
    bool deleteRecord(int id);
    void readAllRecords();
 
 private:
    QSqlDatabase db;
 };


 // DataBaseManager.cppファイル
 
 #include "DataBaseManager.h"
 
 DatabaseManager::DatabaseManager()
 {
    db = QSqlDatabase::addDatabase("QMYSQL");
    db.setHostName("<ホスト名またはIPアドレス  例: localhost>");
    db.setDatabaseName("<データベース名  例: sampledb>");
    db.setUserName("<データベースのユーザ名>");
    db.setPassword("<データベースのユーザ名のパスワード>");
 }
 
 DatabaseManager::~DatabaseManager()
 {
    closeConnection();
 }
 
 // データベースの接続
 bool DatabaseManager::openConnection()
 {
    if (!db.open()) {
       qDebug() << "Error: connection with database failed";
       return false;
    }
    else {
       qDebug() << "Database: connection ok";
       return true;
    }
 }
 
 // データベースの切断
 void DatabaseManager::closeConnection()
 {
    db.close();
 }
 
 // テーブルの作成
 bool DatabaseManager::createTable()
 {
    QSqlQuery query;
    query.prepare("CREATE TABLE IF NOT EXISTS people (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(40) NOT NULL, age INT)");
 
    if (!query.exec()) {
       qDebug() << "Error creating table:" << query.lastError().text();
       return false;
    }
 
    return true;
 }
 
 // 単一のレコードの追加
 bool DatabaseManager::insertRecord(const QString& name, int age)
 {
    QSqlQuery query;
    query.prepare("INSERT INTO people (name, age) VALUES (:name, :age)");
    query.bindValue(":name", name);
    query.bindValue(":age", age);
 
    if (!query.exec()) {
       qDebug() << "Error inserting record:" << query.lastError().text();
       return false;
    }
 
    return true;
 }
 
 // 単一のレコードの更新
 bool DatabaseManager::updateRecord(int id, const QString& name, int age)
 {
    QSqlQuery query;
    query.prepare("UPDATE people SET name = :name, age = :age WHERE id = :id");
    query.bindValue(":id", id);
    query.bindValue(":name", name);
    query.bindValue(":age", age);
 
    if (!query.exec()) {
       qDebug() << "Error updating record:" << query.lastError().text();
       return false;
    }
 
    return true;
 }
 
 bool DatabaseManager::deleteRecord(int id)
 {
    QSqlQuery query;
    query.prepare("DELETE FROM people WHERE id = :id");
    query.bindValue(":id", id);
 
    if (!query.exec()) {
       qDebug() << "Error deleting record:" << query.lastError().text();
       return false;
    }
 
    return true;
 }
 
 // 全てのレコードを読み込む
 void DatabaseManager::readAllRecords()
 {
    QSqlQuery query("SELECT * FROM people");
    while (query.next()) {
       int id = query.value(0).toInt();
       QString name = query.value(1).toString();
       int age = query.value(2).toInt();
       qDebug() << "ID:" << id << "Name:" << name << "Age:" << age;
    }
 }


 // main.cppファイル
 
 int main()
 {
    DatabaseManager dbManager;
 
    if (dbManager.openConnection()) {
       // テーブルの作成
       dbManager.createTable();
 
       // レコードの追加
       dbManager.insertRecord("John Doe", 30);
       dbManager.insertRecord("Jane Smith", 25);
 
       // 全てのレコードを読み込む
       dbManager.readAllRecords();
 
       // 既存のレコードの更新
       dbManager.updateRecord(1, "John Doe Updated", 31);
 
       // 任意のレコードの削除
       dbManager.deleteRecord(2);
 
       // 全てのレコードを読み込む
       dbManager.readAllRecords();
 
       // データーベースを切断
       dbManager.closeConnection();
    }
 
    return 0;
 }



SQLite3

Qtを使用してSQLite3のテーブルにアクセスする場合、まず、QSqlDatabaseクラスを使用してデータベースに接続する。

 #include <QSqlDatabase>
 #include <QSqlQuery>
 
 // SQLiteデータベースに接続する
 QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
 db.setDatabaseName("<SQLiteデータベース名>.sqlite");  // データベースファイル名
 
 if (!db.open())
 {
    qDebug() << "データベースに接続できませんでした。";
    return;
 }


次に、QSqlQueryクラスを使用してクエリを実行する。
以下の例では、テーブルのデータを取得している。

 QSqlQuery query;
 query.prepare("SELECT * FROM <SQLiteデータベースのテーブル名>");
 
 if (query.exec())
 {
    while (query.next())
    {  // レコードの処理
       QString column1 = query.value(0).toString(); // 1番目の列
       QString column2 = query.value(1).toString(); // 2番目の列
 
       // 他の列も同様に取得できる
    }
 }
 else
 {
    qDebug() << "クエリの実行に失敗しました.";
 }
 
 // データベース接続を閉じる
 db.close();



SQLインジェクション対策

SQLインジェクション対策では、プレースホルダを使用してクエリを構築することが重要である。

以下の例では、":username"がプレースホルダとなり、ユーザからの入力等が直接クエリに組み込まれることなく、安全にクエリが実行される。
また、ユーザからの入力をクエリに組み込む場合、入力データを適切にサニタイズしてクエリに含めるようにすることにより、悪意のあるSQLコードが挿入されても実行されないようにする。

 QSqlQuery query;
 QString username = "user_input";  // ユーザからの入力等
 
 // プレースホルダを使用して安全にクエリを構築
 query.prepare("SELECT * FROM users WHERE username = :username");
 query.bindValue(":username", username);
 
 if (query.exec())
 {
    while (query.next())
    {  // レコードの処理
       // ...略
    }
 }
 else
 {
    qDebug() << "クエリの実行に失敗しました.";
 }