project/
├── Makefile
├── get_data.c # 主邏輯:讀配置、連庫、查詢、輸出
├── getfileargv.c # 配置文件解析工具
└── gsp.conf # 配置文件(DBHOST, DBUSER, DBPASSWD, DATABASE)
CC = gcc
# 必須鏈接的庫:MySQL 客戶端 + 網絡 + 數學 + 標準 C + NLS
LIB = -lcurses -lsocket -lmysqlclient -lm -lc -lnsl
all: gspser
gspser: get_data.o getfileargv.o
$(CC) -o gspser get_data.o getfileargv.o $(LIB)
get_data.o: get_data.c
$(CC) -c get_data.c
getfileargv.o: getfileargv.c
$(CC) -c getfileargv.c
clean:
rm -f *.o gspser
注意:庫順序很重要,-lmysqlclient 必須在 -lm -lc 之前,因鏈接器單向解析符號。
#include
#include
#include
#include "/usr/local/mysql/include/mysql.h" // 頭文件路徑按實際安裝調整
#define DBCFG "./gsp.conf"
int main() {
char dbhost[32], dbuser[16], dbpasswd[16], db[16];
char query[256];
int count;
MYSQL *mysql; // 連接句柄
MYSQL_RES *mysql_res; // 結果集
MYSQL_ROW mysql_row; // 行數組
my_ulonglong rows; // 行數類型
// 1. 讀取配置
getfileargv(DBCFG, "DBHOST", dbhost);
getfileargv(DBCFG, "DBUSER", dbuser);
getfileargv(DBCFG, "DBPASSWD", dbpasswd);
getfileargv(DBCFG, "DATABASE", db);
// 2. 初始化 MYSQL 結構
if (!(mysql = mysql_init(NULL))) {
fprintf(stderr, "mysql_init() failed\n");
return 1;
}
// 3. 真實連接(推薦 mysql_real_connect,舊版 mysql_connect 已棄用)
if (!mysql_real_connect(mysql, dbhost, dbuser, dbpasswd, db, 0, NULL, 0)) {
fprintf(stderr, "Connection failed: %s\n", mysql_error(mysql));
mysql_close(mysql);
return 1;
}
// 4. 執行查詢
strcpy(query, "SELECT * FROM zuh WHERE jgm='11110501' ORDER BY zuh");
if (mysql_query(mysql, query)) {
fprintf(stderr, "Query failed: %s\n", mysql_error(mysql));
mysql_close(mysql);
return 1;
}
// 5. 獲取完整結果集(客戶端緩存,適合中小結果集)
mysql_res = mysql_store_result(mysql);
rows = mysql_num_rows(mysql_res);
if (rows == 0) {
printf("無匹配記錄\n");
mysql_free_result(mysql_res);
mysql_close(mysql);
return 0;
}
// 6. 逐行取數並輸出
for (count = 0; count < rows; count++) {
mysql_row = mysql_fetch_row(mysql_res);
if (!mysql_row) break;
printf("社號:%s 組號:%s 組名:%s\n",
mysql_row[0] ? mysql_row[0] : "NULL",
mysql_row[1] ? mysql_row[1] : "NULL",
mysql_row[2] ? mysql_row[2] : "NULL");
}
// 7. 清理資源
mysql_free_result(mysql_res);
mysql_close(mysql);
return 0;
}
#include
#include
int getfileargv(const char *filename, const char *argvname, char *retbuf) {
FILE *fp;
char line[128];
char tempbuf[40];
strncpy(tempbuf, argvname, 30);
tempbuf[39] = '\0';
if ((fp = fopen(filename, "r")) == NULL)
return -1; // 文件打開失敗
strcat(tempbuf, "=");
while (fgets(line, 120, fp)) {
if (line[0] == '#') continue; // 跳過註釋
if (!strncmp(line, tempbuf, strlen(tempbuf))) {
fclose(fp);
line[strlen(line) - 1] = '\0'; // 去換行
strcpy(retbuf, strchr(line, '=') + 1);
return 0; // 成功
}
}
fclose(fp);
return -2; // 未找到鍵
}
# 數據庫連接配置
DBHOST=192.168.1.100
DBUSER=app_user
DBPASSWD=secret123
DATABASE=business_db
make clean && make
./gspser
# 輸出示例:
# 社號:001 組號:10 組名:研發部
# 社號:002 組號:10 組名:測試組
| 現象 | 原因 | 解決 |
|---|---|---|
mysql.h: No such file | 開發包未裝或路徑錯 | ls /usr/local/mysql/include/mysql.h 確認,調整 Makefile Include 路徑 |
undefined reference to mysql_init | 鏈接庫缺失或順序錯 | 確認 -lmysqlclient 在 -lm -lc 前;ldd gspser 檢查動態依賴 |
連接失敗 Can't connect to MySQL server | 宿主/端口/防火牆/skip-networking | 檢查 my.cnf bind-port、telnet host 3306、iptables |
| 中文亂碼 | 字符集不匹配 | 連接後執行 mysql_query(mysql, "SET NAMES gbk") 或 utf8 |
SCO/OpenServer 屬於歷史平台,新項目建議遷移至 Linux(RHEL/CentOS/Ubuntu/Debian)+ MySQL 5.7+/8.0 + GCC 7+/Clang,享受:
mysql_stmt_*)。libmysqlclient 內建、或第三方 mysql-connector-c++)。本文演示了在 SCO OpenServer 上使用 GCC 直接調用 MySQL C API 的完整流程:Makefile 鏈接順序、配置文件解析、連接/查詢/結果集處理的標準四步驟、資源釋放規範。雖平台老舊,但 C API 核心邏輯三十年不變,掌握此基礎可無縫遷移至現代環境。