#include <fcntl.h> // _O_WTEXT
#include <io.h> // _setmode
#include <stdio.h> // _fileno
#include <Windows.h>
#include <sqlext.h>
#include <odbcinst.h>
#include <tchar.h>
#define DRIVER_MAIN _T("Microsoft Access Driver (*.mdb)")
#define DRIVER_SUB _T("Microsoft Text Driver (*.txt; *.csv)")
#define DB_DIR _T("C:\\projects\\vc++\\odbctest\\")
#define DATABASE DB_DIR _T("odbctest.mdb")
#define TABLE _T("09TOCHIG.CSV")
// 関数プロトタイプ宣言
int create_db(void);
int connect_db(SQLHENV henv, SQLHDBC *phdbc, SQLTCHAR *ptcConnStr);
int create_table(SQLHDBC hdbc);
int insert_record(SQLHENV henv, SQLHDBC hdbcMain);
int select_table(SQLHDBC hdbc);
//==============================================================================
int main()
{
SQLHENV henv; // 環境ハンドル
SQLHDBC hdbc; // 接続ハンドル
SQLRETURN rc; // retcode
// BOMなしUTF-16LE
_setmode(_fileno(stdout), _O_WTEXT);
_setmode(_fileno(stderr), _O_WTEXT);
// データベースの作成
if (create_db()) return 1;
// 環境ハンドルの確保
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
// データベースへの接続
if (connect_db(henv, &hdbc, _T("driver={") DRIVER_MAIN _T("}; dbq=") DATABASE))
return 1;
// テーブルの作成
if (create_table(hdbc)) return 1;
// レコードの追加
if (insert_record(henv, hdbc)) return 1;
// 検索
select_table(hdbc);
// 終了処理
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}
//------------------------------------------------------------------------------
int create_db(void)
{
_TCHAR tc;
BOOL b;
if (_taccess(DATABASE, 0) == 0) {
_tprintf(_T("remove %s (y/n)"), DATABASE);
_tscanf_s(_T("%c"), &tc);
if (tc != _T('y')) return -1;
_tremove(DATABASE);
}
b = SQLConfigDataSource(NULL, ODBC_ADD_DSN, DRIVER_MAIN,
_T("create_db=") DATABASE _T("\0"));
if (b == FALSE) {
_ftprintf(stderr, _T("データベースの作成に失敗しました\n"));
return -1;
}
return 0;
}
//------------------------------------------------------------------------------
int connect_db(SQLHENV henv, SQLHDBC *phdbc, SQLTCHAR *ptcConnStr)
{
SQLRETURN rc; // retcode
rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, phdbc);
rc = SQLDriverConnect(*phdbc, NULL, ptcConnStr, SQL_NTS,
NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
if (!SQL_SUCCEEDED(rc)) {
_ftprintf(stderr, _T("データベースへの接続に失敗しました\n"));
return -1;
}
return 0;
}
//------------------------------------------------------------------------------
int create_table(SQLHDBC hdbc)
{
SQLHSTMT hstmt; // 命令ハンドル
SQLRETURN rc; // retcode
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
rc = SQLExecDirect(hstmt, (SQLTCHAR *)
_T("create table 郵便番号データ (")
_T("全国地方公共団体コード text(5),")
_T("旧郵便番号 text(5),")
_T("郵便番号 text(7),")
_T("都道府県名カナ text,")
_T("市区町村名カナ text,")
_T("町域名カナ text(76),")
_T("都道府県名 text,")
_T("市区町村名 text,")
_T("町域名 text(38),")
_T("一町域が二以上の郵便番号で表される場合の表示 byte,")
_T("小字毎に番地が起番されている町域の表示 byte,")
_T("丁目を有する町域の場合の表示 byte,")
_T("一つの郵便番号で二以上の町域を表す場合の表示 byte,")
_T("更新の表示 byte,")
_T("変更理由 byte)")
, SQL_NTS);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
if (!SQL_SUCCEEDED(rc)) {
_ftprintf(stderr, _T("テーブルの作成に失敗しました\n"));
return -1;
}
return 0;
}
//------------------------------------------------------------------------------
int insert_record(SQLHENV henv, SQLHDBC hdbcMain)
{
SQLHDBC hdbcSub; // 接続ハンドル
SQLHSTMT hstmtMain; // 命令ハンドル
SQLHSTMT hstmtSub; // 命令ハンドル
SQLRETURN rc; // retcode
SQLSMALLINT col;
SQLSMALLINT i;
SQLSMALLINT datatype[15];
SQLLEN len;
_TCHAR stmttext[256];
_TCHAR buf[80];
_TCHAR tmp[80];
// サブDBへの接続
if (connect_db(henv, &hdbcSub, _T("driver={") DRIVER_SUB _T("}; dbq=") DB_DIR))
return -1;
// 検索
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbcSub, &hstmtSub);
rc = SQLExecDirect(hstmtSub, (SQLTCHAR *) _T("select * from ") TABLE, SQL_NTS);
if (!SQL_SUCCEEDED(rc)) {
return -1;
}
// データ型の取得
rc = SQLNumResultCols(hstmtSub, &col);
for (i = 0; i < col; i++) {
rc = SQLDescribeCol(hstmtSub, i+1, buf, _countof(buf), NULL,
&datatype[i], NULL, NULL, NULL);
// Text 12 SQL_VARCHAR
// Byte -6 SQL_TINYINT
}
// サブDBからメインDBへの転送ループ
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbcMain, &hstmtMain);
while (1) {
// サブDBから1行読み込み命令文を作る
rc = SQLFetch(hstmtSub);
if (rc == SQL_NO_DATA) break;
if (rc == SQL_ERROR) break;
_tcscpy_s(stmttext, _T("insert into 郵便番号データ values ("));
for (i = 0; i < col; ) {
SQLGetData(hstmtSub, i+1, SQL_C_TCHAR, buf, _countof(buf), &len);
if (len == SQL_NULL_DATA) {
_tcscat_s(stmttext, _T("null"));
} else {
switch (datatype[i]) {
case SQL_VARCHAR:
_stprintf_s(tmp, _T("'%s'"), buf);
_tcscat_s(stmttext, tmp);
break;
default:
_tcscat_s(stmttext, buf);
}
}
_tcscat_s(stmttext, (++i == col) ? _T(")") : _T(","));
}
// メインDBへのレコードの追加
rc = SQLExecDirect(hstmtMain, stmttext, SQL_NTS);
if (!SQL_SUCCEEDED(rc)) {
_ftprintf(stderr, _T("レコードの追加に失敗しました\n"));
return -1;
}
}
SQLFreeHandle(SQL_HANDLE_STMT, hstmtMain);
SQLFreeHandle(SQL_HANDLE_STMT, hstmtSub);
// トランザクション終了
rc = SQLEndTran(SQL_HANDLE_ENV, henv, SQL_COMMIT);
// サブDBへの接続を解除
SQLDisconnect(hdbcSub);
SQLFreeHandle(SQL_HANDLE_DBC, hdbcSub);
return 0;
}
//------------------------------------------------------------------------------
int select_table(SQLHDBC hdbc)
{
SQLHSTMT hstmt; // 命令ハンドル
SQLRETURN rc; // retcode
SQLSMALLINT col;
SQLSMALLINT i;
SQLTCHAR buf[256];
SQLLEN len;
int rec;
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
rc = SQLExecDirect(hstmt, (SQLTCHAR *)_T("select * from 郵便番号データ"), SQL_NTS);
rc = SQLNumResultCols(hstmt, &col);
for (rec = 0; ; rec++) {
rc = SQLFetch(hstmt);
if (rc == SQL_NO_DATA) break;
if (rc == SQL_ERROR) break;
for (i = 1; i <= col; i++) {
rc = SQLGetData(hstmt, i, SQL_C_TCHAR, buf, _countof(buf), &len);
if (len == SQL_NULL_DATA) buf[0] = _T('\0');
_tprintf(_T("%s%c"), buf, (i == col) ? _T('\n') : _T(','));
}
}
_tprintf(_T("レコード数:%d\n"), rec);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
return 0;
}
#if 0
//------------------------------------------------------------------------------
int insert_record(SQLHENV henv, SQLHDBC hdbc)
{
SQLHSTMT hstmt; // 命令ハンドル
SQLRETURN rc; // retcode
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
rc = SQLExecDirect(hstmt, (SQLTCHAR *)
_T("insert into 郵便番号データ(郵便番号,町域名) values ")
_T("('9071801','沖縄県八重山郡与那国町与那国')")
, SQL_NTS);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
if (!SQL_SUCCEEDED(rc)) {
_ftprintf(stderr, _T("レコードの追加に失敗しました\n"));
return -1;
}
rc = SQLEndTran(SQL_HANDLE_ENV, henv, SQL_COMMIT);
return 0;
}
#endif