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

Oracle Pro*C 動態 SQL 方法 3 完整指南:PREPARE、DECLARE、OPEN、FETCH、CLOSE

     編輯:Oracle 資料庫基礎

Pro*C 動態 SQL 三種方法概覽

方法適用場景限制
方法 1無宿主變量的非查詢語句不可用於 SELECT
方法 2輸入宿主變量個數/類型固定的非查詢語句不可用於 SELECT
方法 3選擇列表項與輸入宿主變量個數固定的動態 SQL通用,支援 SELECT 及所有 DML/DDL/DCL

本文重點講解功能最全的方法 3。

方法 3 支援的語句類型

  • DML:INSERT ... VALUES(:a)、DELETE ... WHERE name=:a
  • DDL:CREATE TABLE ...、GRANT ...
  • DCL/事務控制:COMMIT
  • 查詢:SELECT name FROM tbl WHERE no=xxx

不支援:對象名/列名作為宿主變量(如 INSERT INTO :a VALUES(:b))。

五步處理流程

2.1 PREPARE:解析與命名 SQL

EXEC SQL PREPARE statement_name FROM { :host_string | string_literal };
  • statement_name:預編譯器標識符(非字符串變量)。
  • host_string:包含 SQL 文本的宿主變量(如 char sql_buf[1024])。
  • string_literal:直接寫死的 SQL 字符串。

2.2 DECLARE CURSOR:定義游標關聯 PREPARE 語句

EXEC SQL DECLARE cursor_name CURSOR FOR statement_name;
  • cursor_name:游標名稱。
  • statement_name:PREPARE 時使用的標識符。

2.3 OPEN:打開游標並執行

EXEC SQL OPEN cursor_name [USING host_variable_list];
  • 非 SELECT:直接執行語句,隨後可 CLOSE。
  • SELECT:將結果集放入游標,需 FETCH 處理後再 CLOSE。
  • USING 子句綁定輸入宿主變量(對應 SQL 中的 :var)。

2.4 FETCH:提取查詢結果

EXEC SQL FETCH cursor_name INTO host_variable_list;
  • 將游標當前行數據映射到宿主變量(結構體或變量列表)。
  • 循環 FETCH 直到 sqlca.sqlcode == 1403 (NO_DATA_FOUND)。

2.5 CLOSE:關閉游標釋放資源

EXEC SQL CLOSE cursor_name;

完整代碼示例:動態構建查詢條件

/* 大組成員表結構 */
struct GrpMember {
  char str_bgID[22];  /* 大組ID */
  char str_matID[22]; /* 素材ID */
  ...
};

/* 素材檢索:根據輸入結構動態構建 WHERE 條件 */
void MatSearch(struct GrpMember *in) {
  char buf[256];
  EXEC SQL BEGIN DECLARE SECTION;
    char sql_buf[1024];
    struct GrpMember ret;
  EXEC SQL END DECLARE SECTION;

  /* 1. 構建基礎 SQL */
  strcpy(sql_buf, "SELECT * FROM TBL_GRPMEMBER WHERE 1=1 ");

  /* 2. 根據非空字段動態拼接條件 */
  if (!isEmpty(in->str_bgID)) {
    sprintf(buf, "AND tbl_str_bgID = %s ", in->str_bgID);
    strcat(sql_buf, buf);
  }
  /* ... 其他字段類似 ... */

  /* 3. PREPARE */
  EXEC SQL PREPARE sql_stmt FROM :sql_buf;

  /* 4. DECLARE CURSOR */
  EXEC SQL DECLARE c1 CURSOR FOR sql_stmt;

  /* 5. OPEN:執行查詢 */
  EXEC SQL OPEN c1;

  /* 6. FETCH 循環處理結果 */
  while (1) {
    EXEC SQL FETCH c1 INTO :ret;  /* 實際應逐項 INTO,逗號分隔 */
    if (sqlca.sqlcode == 1403) break;  /* NO_DATA_FOUND */
    /* 處理 ret ... */
  }

  /* 7. CLOSE */
  EXEC SQL CLOSE c1;
}

關鍵注意事項

  1. 宿主變量聲明:必須在 EXEC SQL BEGIN/END DECLARE SECTION 區塊中聲明。
  2. 指針 vs 值:FETCH INTO :ret 中 ret 為結構體變量,Pro*C 自動處理成員映射;若用指針需確保內存有效。
  3. 錯誤處理:每步檢查 sqlca.sqlcode,非零即異常。
  4. SQL 注入風險:動態拼接 SQL 時,數值型字段直接拼接相對安全,字符型字段必須使用綁定變量(WHERE name = :bv)而非字符串拼接,否則極易遭受注入攻擊。
  5. 性能:重複執行相同 SQL 結構時,PREPARE 只需一次,後續只需 RE-OPEN/RE-FETCH,避免重複解析。

總結

Pro*C 動態 SQL 方法 3 通過 PREPARE/DECLARE/OPEN/FETCH/CLOSE 五步流程,實現了運行時構建並執行任意 SQL(含查詢)的能力。核心優勢在於靈活性:WHERE 條件、排序、甚至部分 DDL 可動態生成。生產環境中務必結合綁定變量防注入,並做好錯誤碼檢查與資源釋放。

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