首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

C 語言呼叫 MySQL 存儲過程完整範例:IN/OUT 參數傳遞、錯誤碼返回與結果集獲取

     編輯:MySQL 綜合教學

C 語言呼叫 MySQL 存儲過程完整範例:IN/OUT 參數傳遞、錯誤碼返回與結果集獲取

存儲過程將業務邏輯下沉到資料庫層,C 語言透過 CALL 語句調用,利用 CLIENT_MULTI_STATEMENTS 支援多結果集,並透過用戶變數 @out_param 獲取 OUT 參數。本文提供完整可編譯範例:建表、存儲過程、C 代碼、編譯執行。

1. 業務場景與表結構

選課記錄表 sc:cno(課程號)、sno(學號)、ordinary_score(平時分)、last_score(卷面分)、all_score(總分)。

CREATE TABLE sc (
  cno VARCHAR(8) NOT NULL,
  sno VARCHAR(8) NOT NULL,
  ordinary_score INT,
  last_score INT,
  all_score INT
);

2. 存儲過程:cal_grade

輸入:平時分 x、卷面分 y、平時分權重 pert、學號 s、課程號 c。
輸出:OUT 參數 t (總分或錯誤碼 -1/-2)。

DELIMITER //
CREATE PROCEDURE cal_grade(
  IN x INT, IN y INT, OUT t INT, IN pert FLOAT, IN s VARCHAR(8), IN c VARCHAR(8)
)
LABEL_PROC: BEGIN
  IF (x < 0 || x > 100) THEN SET t = -1; LEAVE LABEL_PROC; END IF;
  IF (y < 0 || y > 100) THEN SET t = -2; LEAVE LABEL_PROC; END IF;
  SET t = ROUND(x * pert + y * (1 - pert));
  UPDATE sc SET ordinary_score = x, last_score = y WHERE sno = s AND cno = c;
END LABEL_PROC //
DELIMITER ;

3. C 語言調用代碼

#include 
#include "mysql.h"

int main() {
  MYSQL *conn;
  MYSQL_RES *res;
  MYSQL_ROW row;
  char buf[100];

  conn = mysql_init(NULL);
  // 關鍵:CLIENT_MULTI_STATEMENTS 允許 CALL + 後續 SELECT @t
  conn = mysql_real_connect(conn, "localhost", "root", "root", "test", 0, NULL, CLIENT_MULTI_STATEMENTS);
  if (!conn) {
    fprintf(stderr, "Connect failed: %s\n", mysql_error(conn));
    return 1;
  }

  // 呼叫存儲過程,OUT 參數寫入用戶變數 @t
  sprintf(buf, "CALL cal_grade(%d, %d, @t, %f, '%s', '%s')", 10, 10, 0.3, "123", "456");
  if (mysql_query(conn, buf)) {
    fprintf(stderr, "CALL failed: %s\n", mysql_error(conn));
    mysql_close(conn);
    return 1;
  }

  // 獲取 OUT 參數
  if (mysql_query(conn, "SELECT @t")) {
    fprintf(stderr, "SELECT @t failed: %s\n", mysql_error(conn));
    mysql_close(conn);
    return 1;
  }

  res = mysql_store_result(conn);
  if (res) {
    row = mysql_fetch_row(res);
    if (row && row[0]) {
      if (strcmp(row[0], "-1") == 0) printf("平時分不在範圍內\n");
      else if (strcmp(row[0], "-2") == 0) printf("卷面分不在範圍內\n");
      else printf("總分為: %s\n", row[0]);
    }
    mysql_free_result(res);
  }

  mysql_close(conn);
  return 0;
}

4. 編譯與執行

gcc -o call_proc call_proc.c -I/usr/local/include/mysql -L/usr/local/lib/mysql -lmysqlclient -lz -lm
./call_proc

5. 關鍵技術點總結

技術點說明
CLIENT_MULTI_STATEMENTS連線參數必須帶上,否則 CALL 後無法執行後續 SELECT @t,報錯 PROCEDURE can't return a result set in the given context
OUT 參數獲取MySQL 存儲過程 OUT 參數寫入用戶變數 @var,需額外 SELECT @var 讀取
錯誤碼設計約定負數為錯誤碼 (如 -1, -2),正數為正常業務返回值
標籤跳出存儲過程中 LEAVE LABEL 實現提前返回,避免深層巢狀 IF
參數模式IN (預設, 傳入)、OUT (傳出)、INOUT (雙向)

6. 生產環境建議

  • 使用預處理語句 mysql_stmt_prepare("CALL cal_grade(?, ?, @t, ?, ?, ?)") 綁定參數,防注入、提升重複調用效能。
  • 封裝通用 call_proc(proc_name, in_params..., out_param_names...) 函數,簡化業務代碼。
  • 異常處理:檢查每個 API 返回值,記錄 mysql_error()、mysql_sqlstate()。

掌握「CALL + SELECT @out」雙語句模式與 CLIENT_MULTI_STATEMENTS 連線選項,即可在 C/C++ 系統中高效複用資料庫端業務邏輯。

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