MFCでDBテーブルを操作したい話 4(最終回)

前回までの話

再度挑戦

2話目において実践した、MySQL Connector C++を利用して
テーブル操作を行いたいです。

再度、ボタンを押した際のソース掲示。

void CMySQLTest1Dlg::OnBnClickedButton1()
{
	sql::SQLString strHost = "tcp://127.0.0.1:3306";	// ホスト名
	sql::SQLString strUser = "root";					// ユーザ名
	sql::SQLString strPass = "password";				// パスワード
	// ※パスワードは、前回設定したものを入れる

	try
	{
		// MySQLドライバのインスタンス取得
		sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();

		// DB接続情報を設定。
		std::unique_ptr<sql::Connection> con(driver->connect(strHost, strUser, strPass));

		//ここまで来たら、接続できた
		AfxMessageBox(_T("接続成功"));
	}
	catch (sql::SQLException& e)
	{
		// 接続できなかった
		CString errorMessage = _T("");
		errorMessage.Format(_T("エラー: %s\r\nエラーコード: %d"), CString(e.what()), e.getErrorCode());
		AfxMessageBox(errorMessage, MB_OK | MB_ICONERROR);
	}
}

try文の、接続成功メッセージ以降を追加していきます。

void CMySQLTest1Dlg::OnBnClickedButton1()
{
	sql::SQLString strHost = "tcp://127.0.0.1:3306";	// ホスト名
	sql::SQLString strUser = "root";					// ユーザ名
	sql::SQLString strPass = "password";         		// パスワード
	// ※パスワードは、前回設定したものを入れる

		try
	{
		// MySQLドライバのインスタンス取得
		sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();
		//sql::SQLString strOpt = "SET NAMES utf8mb4";

		// DB接続情報を設定。
		std::unique_ptr<sql::Connection> con(driver->connect(strHost, strUser, strPass));

		//ここまで来たら、接続できた
		//AfxMessageBox(_T("接続成功"));
		//con->setClientOption("OPT_CHARSET_NAME", "utf8mb4"); // これでクライアント側の文字セットを設定
		// スキーマを設定
		con->setSchema("testschema1");

		// クエリを実行
		std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement("SELECT name FROM testtable1 WHERE id = ?"));
		pstmt->setInt(1, 1);

		std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());

		CString strDisp = _T("");	// 表示用
		// 結果を処理
		if (res->next()) 
		{
			do
			{
				std::string name = res->getString("name");
				// UTF-8からUTF-16への変換
				int len = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, NULL, 0);
				if (len > 0)
				{
					std::wstring wideName(len, 0);
					MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, &wideName[0], len);

					// std::wstringからCStringに変換
					CString cstrName(wideName.c_str());
					strDisp += cstrName;
					strDisp += _T("\r\n");
				}
				else
				{
					strDisp =_T("UTF - 8からUTF - 16への変換に失敗しました。");
					break;
				}
			} while (res->next());
		}
		else 
		{
			strDisp = _T("idが1のデータが見つかりませんでした。");
		}

		AfxMessageBox(strDisp, MB_OK | MB_ICONINFORMATION);
	}
	catch (sql::SQLException& e)
	{
		// 接続できなかった
		CString errorMessage = _T("");
		errorMessage.Format(_T("エラー: %s\r\nエラーコード: %d"), CString(e.what()), e.getErrorCode());
		AfxMessageBox(errorMessage, MB_OK | MB_ICONERROR);
	}
}

17行目でスキーマを設定、20と21行目でSQL文を発行、23行目で実行です。
後は文字化けしないよう処理を加えて、cstrNameを表示させます。

処理実行

前回成功したとき同様、リリースモードでビルドします。

今のテーブルはこんな感じです。

ソースに書いたSQL文は以下と同じです。

SELECT name FROM testtable1 WHERE id = 1;

出来上がったexe上のボタンを押すと。

やっと…できた…!
長かった(;´∀`)

他にも試す

ソース上のSQLを変えてみます。
ボタンやエディットボックス増やして色んなパターンを試す方もいいですが、
コントロール増やすの面倒なので()、
今回はソースを変更します。

SELECT name FROM testtable1 WHERE age = 20;

SQL発行の箇所を変更します。

       // クエリを実行
		std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement("SELECT name FROM testtable1 WHERE age = ?"));
		pstmt->setInt(1, 20);

age列が20は、id=1とid=11がいますが、果たして

良さげ。

INSERT 文

INSERTを行います。

	// クエリを実行
	std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement("INSERT INTO testtable1 VALUES (?, ?, ?)"));
	pstmt->setInt(1, 25);
	pstmt->setString(2, "Mike Davis");
	pstmt->setInt(3, 70);

	//std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
	pstmt->executeUpdate();

	/*
	CString strDisp = _T("");	// 表示用
	// 結果を処理
	if (res->next()) 
	{
		// 略
	}
	else 
	{
		// 略
	}
	*/

調べていて少し意外だったのが、name列にシングルクォーテーションは必要ないみたいです。
寧ろ、シングルクォーテーションがあるとエラーが出てきてしまいました。

そして7行目の代わりに8行目を使います。
executeQueryは通常、データの取得 (SELECT文) に使用され、
executeUpdateはデータの変更 (INSERT, UPDATE, DELETE 文) に使用されます。

ビルドしてボタンを押し、テーブルを見に行くと

反映されました。

因みに、名前に全角文字を使用した場合、エラーが出てきます。

SELECTのとき同様、UTF16⇔UTF8変換をすれば行けそうな気がしますが、
ちょっと力尽きてしまい、今回は断念します。

これは課題ということで。

DELETE文

INSERTができればDELETEも問題なくできるでしょうけど。

	// クエリを実行	
	std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement("DELETE FROM testtable1 WHERE id = ?"));
	pstmt->setInt(1, 11);
	pstmt->executeUpdate();

id=11の行を削除します。

ビルド、実行すると

削除確認できました。
さらば、律ちゃん。

終わりに

MySQL Connector C++を使って、MySQLのテーブル操作を行う話でした。

正直ここまでできるとは思ってなかったし、
課題たくさん出てきたけど、ちょっとずつ理解を深めたいです。

少しずつだけど、できることが多くなって少し嬉しいです。

今回はここまで。

コメント

タイトルとURLをコピーしました