introbotics’s blog

人工知能、機械の心について思いついたことを並べてます

スポンサーリンク

visual stdio c++ からデータベース(localdb)のSQL実行

DB接続までは前記事を参照


SQLの実行 (create database)

下記を追加

SQLHSTMT	hstmt = SQL_NULL_HSTMT;

// ステートメントハンドルを作成
res = ::SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
			
//if (!SQL_SUCCEEDED(res)) { strErr = L"ステートメントハンドル作成";}
// SQL実行(データベース作成)
res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"CREATE DATABASE TestDB", SQL_NTS);

SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, szState, &nErrorCode, szErrorMsg, sizeof(szErrorMsg), &nSize);
std::wcout << L"connect error State=[" << szState << L"] ErrorMsg[" << szErrorMsg << L"]" << std::endl;
::SQLCloseCursor(hstmt);
SQLでのデータベース参照

データベースのデータは下記を想定
[TestTable]
id name price
1 object1 100
2 object2 328
3 object3 30

[ソース]

// ステートメントハンドルを作成
SQLHSTMT	hstmt = SQL_NULL_HSTMT;
SQLLEN    nColLen;
res = ::SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"SELECT * FROM TestTable", SQL_NTS);
if (SQL_SUCCEEDED(res))
{
  SQLINTEGER id = 0;
	SQLWCHAR name[20 + 1] = { L"" };
	SQLINTEGER price = 0;
	::SQLBindCol(hstmt, 1, SQL_C_SLONG, &id, sizeof(id), &nColLen);
	::SQLBindCol(hstmt, 2, SQL_C_WCHAR, &name, sizeof(name), &nColLen);
	::SQLBindCol(hstmt, 3, SQL_C_SLONG, &price, sizeof(price), &nColLen);
	while (SQL_SUCCEEDED(::SQLFetch(hstmt)))
		std::wcout << id << L", " << name << L", " << price << std::endl;
	}
	::SQLCloseCursor(hstmt);

SQLBindColへ与える値は下記

SQLBindCol(ステートメントハンドル,参照するDBの列,データ型,代入先変数のポインタ,変数バッファの長さ,SQL_NULL_DATA)
SQLでのデータベース追加(insert)

※テーブル名はdbo.table、テーブルの内容もテスト時のパラメータ(t, e, c,h,p,ex,ey,px,py,con,w)

[ソース]

// ステートメントハンドルを作成
SQLHSTMT	hstmt = SQL_NULL_HSTMT;
SQLLEN    nColLen;
res = ::SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
			res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"INSERT INTO [dbo].[Table](t, e, c,h,p,ex,ey,px,py,con,w) VALUES(3, 5, 200,2,3,5,1,23,3,11,3)", SQL_NTS);
::SQLCloseCursor(hstmt);
SQLでのデータベース更新(update)

※テーブル名はTestTable、テーブル内容はテスト用テーブル

SQLHSTMT	hstmt = SQL_NULL_HSTMT;
SQLLEN    nColLen;
			res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"UPDATE TestTable SET t=15 WHERE id=5", SQL_NTS);
			
::SQLCloseCursor(hstmt);
前記事も含めたDB接続⇒SQL実行までの一連ソース
#include <iostream>
#include <windows.h>

#include <sql.h>	
#include <sqlext.h>	
#include <sqltypes.h>	
#include <sqlucode.h>	
#pragma comment(lib, "odbc32.lib")
using namespace std;

int main()
{
	SQLRETURN res;

	SQLHANDLE	henv = SQL_NULL_HANDLE;
	SQLHDBC		hdbc = SQL_NULL_HANDLE;
	SQLHSTMT	hstmt = SQL_NULL_HSTMT;
	SQLWCHAR	szConnStrOut[1024] = { L'tmpszConnStrOut' };
	SQLSMALLINT cchConnStrOut = 0;
	SQLWCHAR	szState[6] = { L'tmpszState' };
	SQLWCHAR	szErrorMsg[1024] = { L'tmpszErrorMsg' };
	//SQLWCHAR	strErr[1024] = { L'tmpstrErr' };
	SQLINTEGER  nErrorCode = 0;
	SQLSMALLINT nSize = 0;
	wcout.imbue(std::locale("Japanese"));//wcoutでの日本語出力に必要

	// 環境ハンドルの作成
	res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
	if (SQL_SUCCEEDED(res)) {
		res = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, reinterpret_cast<SQLPOINTER>(SQL_OV_ODBC3), 0);

		// 接続ハンドルの作成
		res = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

		if (SQL_SUCCEEDED(res)) {
			// データベースへ接続
			res = SQLDriverConnect(hdbc, NULL, (SQLWCHAR*)L"dsn=ProjectsV13;DRIVER={SQL SERVER Native Client 11.0};database=database2;Integrated Security=True;Trusted_Connection=Yes;", SQL_NTS, szConnStrOut, 1024, &cchConnStrOut, SQL_DRIVER_NOPROMPT);
			std::wcout << L"szConnStrOut=[" << szConnStrOut << L']' << std::endl;

			if (SQL_SUCCEEDED(res)) {
				printf("接続成功\n");
			}
			else {
				SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, szState, &nErrorCode, szErrorMsg, sizeof(szErrorMsg), &nSize);
				std::wcout << L"connect error State=[" << szState << L"] ErrorMsg[" << szErrorMsg << L"]" << std::endl;
			}

			// ステートメントハンドルを作成
			res = ::SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
			
			//if (!SQL_SUCCEEDED(res)) { strErr = L"ステートメントハンドル作成";}
			SQLLEN    nColLen;

			// SQL実行(データベース作成)
			res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"CREATE DATABASE TestDB", SQL_NTS);

			SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, szState, &nErrorCode, szErrorMsg, sizeof(szErrorMsg), &nSize);
			std::wcout << L"connect error State=[" << szState << L"] ErrorMsg[" << szErrorMsg << L"]" << std::endl;
			::SQLCloseCursor(hstmt);

			//SQL実行  データ追加(insert)
			res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"INSERT INTO [dbo].[Table](t, e, c,h,p,ex,ey,px,py,con,w) VALUES(3, 5, 200,2,3,5,1,23,3,11,3)", SQL_NTS);
			if (SQL_SUCCEEDED(res))
			{
				SQLLEN cnt = 0;
				res = ::SQLRowCount(hstmt, &cnt);
				std::wcout << L"SQL実行 INSERT 1 : " << cnt << L" 行  処理されました。" << std::endl;
			}
			::SQLCloseCursor(hstmt);

			//SQL実行  データ更新(Update)
			res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"UPDATE TestTable SET t=15 WHERE id=5", SQL_NTS);
			if (SQL_SUCCEEDED(res))
			{
				SQLLEN cnt = 0;
				res = ::SQLRowCount(hstmt, &cnt);
				std::wcout << L"SQL実行 update 1 : " << cnt << L" 行  処理されました。" << std::endl;
			}
			::SQLCloseCursor(hstmt);

			//SQL実行  データ参照(SELECT)
			res = ::SQLExecDirect(hstmt, (SQLWCHAR*)L"SELECT * FROM TestTable", SQL_NTS);
			if (SQL_SUCCEEDED(res))
			{
				SQLINTEGER id = 0;
				SQLWCHAR name[20 + 1] = { L"" };
				SQLINTEGER price = 0;
				::SQLBindCol(hstmt, 1, SQL_C_SLONG, &id, sizeof(id), &nColLen);
				::SQLBindCol(hstmt, 2, SQL_C_WCHAR, &name, sizeof(name), &nColLen);
				::SQLBindCol(hstmt, 3, SQL_C_SLONG, &price, sizeof(price), &nColLen);
				while (SQL_SUCCEEDED(::SQLFetch(hstmt)))
					std::wcout << id << L", " << name << L", " << price << std::endl;
			}
			::SQLCloseCursor(hstmt);

			SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, szState, &nErrorCode, szErrorMsg, sizeof(szErrorMsg), &nSize);
			std::wcout << L"connect error State=[" << szState << L"] ErrorMsg[" << szErrorMsg << L"]" << std::endl;


			//終了処理
			SQLDisconnect(hdbc);
			SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
		}
	}
	SQLFreeHandle(SQL_HANDLE_ENV, henv);

	return 0;
}//Main