首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言操作 MariaDB/MySQL 實戰:動態拼接跨月分表查詢 SQL

     編輯:關於C語言

C語言操作 MariaDB/MySQL 實戰:動態拼接跨月分表查詢 SQL

專案背景與需求

業務資料庫採「按天分表」:2016_6_1_oss_musicelves、2016_6_2_oss_musicelves … 現需「按月統計」某玩家特定事件次數。純 SQL 寫法極其複雜,改用 C 程式動態拼接 UNION ALL 查詢,再彙總。

環境建置 (Ubuntu 16.04)


# 安裝 MariaDB 伺服器與開發套件
sudo apt-get install mariadb-server mariadb-client \
    libmariadb2 libmariadb-client-lgpl-dev

# 建立測試資料庫與分表
mysql -u root -p < mariadb_test.sql

mariadb_test.sql 內容:建立 oss_log 資料庫、匯入基礎表 oss_musicelves、以 CREATE TABLE ... SELECT 批量建立 8 張分表。

Shell 腳本快速原型驗證


#!/bin/sh
# getmouths.sh ptid [month] [year]
ptid=$1
mouth=${2:-$(date +%m | sed 's/^0//')}
year=${3:-$(date +%Y)}

tbname="${year}_${mouth}_%_oss_musicelves"
mysql -e "SELECT DISTINCT table_name FROM information_schema.columns \
    WHERE table_name LIKE '$tbname'" | awk 'NR>1' | while read name; do
    mysql -e "SELECT COUNT(*) FROM oss_log.$name \
        WHERE specifytype=1 AND char_id=$ptid" | awk 'NR>1' >> __tmp
done
sum=$(awk '{s+=$1} END {print s}' __tmp)
echo "$year-$mouth sum: $sum"

C 語言完整實作 getmouths.c

核心邏輯

  1. 解析命令列參數:ptid、月份、年份(預設為當月)。
  2. 連線 MariaDB:使用一般帳號 csz(僅 SELECT 權限),啟用 --skip-grant-tables 繞過預設只允許本地 root 登入。
  3. 查詢 information_schema.columns 取得符合 YYYY_MM_%_oss_musicelves 模式的所有表名。
  4. 動態拼接 SQL:
    SELECT SUM(c) FROM ( SELECT COUNT(*) AS c FROM t1 WHERE ... UNION ALL SELECT COUNT(*) FROM t2 WHERE ... ... ) AS t;
  5. 執行彙總查詢,輸出結果。

關鍵程式碼片段


#define _INT_BUF 4096
#define _STR_SQLTABLES \
    "SELECT DISTINCT table_name FROM information_schema.columns \
     WHERE table_name LIKE '%d_%d_%%_oss_musicelves'"
#define _STR_SQLSELECT \
    "SELECT COUNT(*) AS c FROM %s WHERE specifytype=1 AND char_id = %lld"

MYSQL *con = mysql_init(NULL);
mysql_real_connect(con, "127.0.0.1", "csz", "1314222", "oss_log", 0, NULL, 0);

/* 1. 取得分表清單 */
sprintf(sql, _STR_SQLTABLES, year, month);
mysql_query(con, sql);
MYSQL_RES *res = mysql_store_result(con);

/* 2. 動態拼接 UNION ALL */
int first = 1, len = 0;
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
    if (first) {
        len = sprintf(sql, "SELECT SUM(c) FROM (\n" _STR_SQLSELECT, row[0], ptid);
        first = 0;
    } else {
        len += sprintf(sql + len, "\nUNION ALL\n" _STR_SQLSELECT, row[0], ptid);
    }
}
sprintf(sql + len, "\n) AS t;");

/* 3. 執行彙總查詢 */
mysql_free_result(res);
mysql_query(con, sql);
res = mysql_store_result(con);
if ((row = mysql_fetch_row(res)))
    printf("sum %lld %d/%d: %s\n", ptid, year, month, row[0]);

mysql_free_result(res);
mysql_close(con);

編譯與執行


gcc -Wall -ggdb2 -I/usr/include/mariadb -o getmouths.out getmouths.c -lmysqlclient
./getmouths.out 30422720614402293 6 2016

MariaDB C API 關鍵函式速查

函式用途
mysql_init()初始化 MYSQL 結構體
mysql_real_connect()建立真實連線
mysql_query()執行 SQL 陳述式
mysql_store_result()取得完整結果集(客戶端緩衝)
mysql_fetch_row()逐列取得資料
mysql_free_result()釋放結果集記憶體
mysql_close()關閉連線
mysql_error()取得最近一次錯誤訊息

權限與安全性最佳實務

  • 建立專用唯讀帳號:GRANT SELECT ON oss_log.* TO 'csz'@'%' IDENTIFIED BY '...';
  • 避免在程式碼硬編碼密碼,改用環境變數或設定檔讀取。
  • 生產環境務必啟用 SSL 連線(mysql_ssl_set)。
  • 使用 PREPARE STATEMENT 參數化查詢防止 SQL Injection(本範例因動態表名無法參數化,需嚴格驗證輸入)。

總結

C 搭配 MariaDB C API 處理動態跨表查詢,靈活度遠高於純 SQL 或 Shell。掌握 mysql_store_result + 動態字串拼接 模式,可應對各類分表、分庫彙總需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved