搭配使用 Visual FoxPro ODBC Driver 與 C 或 Visual C++ 應用程式
C 或 C++ 應用程式會將 SQLExecute 或 SQLExecDirect 陳述式傳送至 Visual FoxPro,以與 Visual FoxPro 通訊。 此陳述式可以包含下列內容:
Visual FoxPro 語言原生的 SQL 陳述式,例如 DROP TABLE 命令。
非 SQL Visual FoxPro 語言,例如支援的 SET 命令。
如需 Visual FoxPro 原生 SQL 的詳細資訊,請參閱 Visual FoxPro 文件。
範例:搭配使用 Visual FoxPro ODBC Driver 與 C 或 C++ 應用程式
下列範例會使用 ODBC C API 來擷取儲存在 Microsoft Visual FoxPro 範例資料庫之 Microsoft Visual FoxPro 範例資料庫中員工數據表中last_name字段中的數據。 此資料庫隨附 Visual FoxPro 提供,預設會安裝在下列位置:
c:\vfp\samples\mainsamp\data\tastrade.dbc
此範例會一次顯示一個姓氏,讓您按一下訊息方塊上的 [確定],查看下一個姓氏。 此處預設已設定名為 Tastrade 的資料來源,用於使用 Tastrade.dbc 資料庫。
注意
您應該在所有 ODBC API 呼叫上執行錯誤檢查。為了簡潔起見,此範例會排除錯誤檢查的部分。
// FoxPro_ODBC_Driver_with_C.cpp
// compile with: odbc32.lib user32.lib /c
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
#include <mbstring.h>
#define MAX_DATA 100
#define MYSQLSUCCESS(rc) ((rc==SQL_SUCCESS)||(rc==SQL_SUCCESS_WITH_INFO))
class direxec {
RETCODE rc; // ODBC return code
HENV henv; // Environment
HDBC hdbc; // Connection handle
HSTMT hstmt; // Statement handle
unsigned char szData[MAX_DATA]; // Returned data storage
SDWORD cbData; // Output length of data
unsigned char chr_ds_name[SQL_MAX_DSN_LENGTH]; // Data source name
public:
direxec(); // Constructor
void sqlconn(); // Allocate env, stat, and conn
void sqlexec(unsigned char *); // Execute SQL statement
void sqldisconn(); // Free pointers to env, stat, conn, and disconnect
void error_out(); // Displays errors
};
// Constructor initializes the string chr_ds_name with the data source name.
direxec::direxec() {
_mbscpy_s(chr_ds_name, (const unsigned char *)"tastrade");
}
// Allocate environment handle, allocate connection handle,
// connect to data source, and allocate statement handle.
void direxec::sqlconn() {
SQLAllocEnv(&henv);
SQLAllocConnect(henv, &hdbc);
rc=SQLConnect(hdbc, chr_ds_name, SQL_NTS, NULL, 0, NULL, 0);
// Deallocate handles, display error message, and exit.
if (!MYSQLSUCCESS(rc)) {
SQLFreeEnv(henv);
SQLFreeConnect(hdbc);
error_out();
exit(-1);
}
rc = SQLAllocStmt(hdbc, &hstmt);
}
// Execute SQL command with SQLExecDirect() ODBC API.
void direxec::sqlexec(unsigned char * cmdstr) {
rc = SQLExecDirect(hstmt, cmdstr, SQL_NTS);
if (!MYSQLSUCCESS(rc)) { // Error
error_out();
// Deallocate handles and disconnect.
SQLFreeStmt(hstmt, SQL_DROP);
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
SQLFreeEnv(henv);
exit(-1);
}
else {
for (rc = SQLFetch(hstmt) ; rc == SQL_SUCCESS; rc=SQLFetch(hstmt)) {
SQLGetData(hstmt, 1, SQL_C_CHAR, szData, sizeof(szData), &cbData);
// In this example, the data is returned in a messagebox for
// simplicity. However, normally the SQLBindCol() ODBC API could
// be called to bind individual data rows and assign for a rowset.
MessageBox(NULL, (const char *)szData, "ODBC", MB_OK);
}
}
}
// Free the statement handle, disconnect, free the connection handle, and
// free the environment handle.
void direxec::sqldisconn() {
SQLFreeStmt(hstmt, SQL_DROP);
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
SQLFreeEnv(henv);
}
// Display error message in a message box that has an OK button.
void direxec::error_out() {
unsigned char szSQLSTATE[10];
SDWORD nErr;
unsigned char msg[SQL_MAX_MESSAGE_LENGTH + 1];
SWORD cbmsg;
while(SQLError(0, 0, hstmt, szSQLSTATE, &nErr, msg, sizeof(msg), &cbmsg) == SQL_SUCCESS) {
sprintf_s((char *)szData, MAX_DATA, "Error:\nSQLSTATE=%s, Native error=%ld, msg='%s'",
szSQLSTATE, nErr, msg);
MessageBox(NULL, (const char *)szData, "ODBC Error", MB_OK);
}
}
int main (){
// Declare an instance of the direxec object.
direxec x;
// Allocate handles and connect.
x.sqlconn();
// Execute SQL command "SELECT last_name FROM employee".
x.sqlexec((UCHAR FAR *)"SELECT last_name FROM employee");
// Free handles, and disconnect.
x.sqldisconn();
// Return success code; example executed successfully.
return (TRUE);
}