6.2.2 C API 預處理語句類型轉換

預處理語句使用用戶端 C 語言變數(對應於伺服器端的 SQL 值)在用戶端和伺服器之間傳輸資料。如果用戶端 C 變數類型與伺服器端對應的 SQL 值類型不符,MySQL 會在兩個方向執行隱式類型轉換。

MySQL 知道伺服器端 SQL 值的類型代碼。MYSQL_BIND 結構中的 buffer_type 值表示用戶端上儲存值的 C 變數的類型代碼。這兩個代碼一起告訴 MySQL 必須執行哪些轉換(如果有的話)。以下是一些範例

  • 如果您使用 MYSQL_TYPE_LONGint 變數,將整數值傳遞到要儲存在 FLOAT 欄位的伺服器,MySQL 會先將該值轉換為浮點數格式,然後再儲存。

  • 如果您擷取 SQL MEDIUMINT 欄位值,但指定 buffer_type 值為 MYSQL_TYPE_LONGLONG,並使用 long long int 類型的 C 變數作為目標緩衝區,MySQL 會將 MEDIUMINT 值(需要少於 8 個位元組)轉換為 long long int(一個 8 位元組變數)進行儲存。

  • 如果您將值為 255 的數值欄位擷取到 char[4] 字元陣列中,並指定 buffer_type 值為 MYSQL_TYPE_STRING,則陣列中的結果值為 4 位元組字串 '255\0'

  • MySQL 會將 DECIMAL 值做為原始伺服器端值的字串表示傳回,這就是對應的 C 類型為 char[] 的原因。例如,12.345 會以 '12.345' 的形式傳回給用戶端。如果您指定 MYSQL_TYPE_NEWDECIMAL,並將字串緩衝區繫結到 MYSQL_BIND 結構,則 mysql_stmt_fetch() 會將該值以字串形式儲存在緩衝區中,而不進行轉換。如果改為指定數值變數和類型代碼,則 mysql_stmt_fetch() 會將字串格式的 DECIMAL 值轉換為數值格式。

  • 對於 MYSQL_TYPE_BIT 類型代碼,BIT 值會傳回至字串緩衝區,這就是對應的 C 類型為 char[] 的原因。該值表示需要在用戶端進行解譯的位元字串。若要將值傳回為更容易處理的類型,可以使用以下任一類型的運算式,將值轉換為整數

    SELECT bit_col + 0 FROM t
    SELECT CAST(bit_col AS UNSIGNED) FROM t

    若要擷取該值,請繫結一個足以容納該值的整數變數,並指定適當的對應整數類型代碼。

在將變數繫結到用於擷取欄位值的 MYSQL_BIND 結構之前,您可以檢查結果集中每個欄位的類型代碼。如果您想判斷最適合使用的變數類型以避免類型轉換,這可能會是理想的做法。若要取得類型代碼,請在使用 mysql_stmt_execute() 執行語句後,呼叫 mysql_stmt_result_metadata()。中繼資料提供對結果集類型代碼的存取權限,如第 6.4.24 節「mysql_stmt_result_metadata()」第 5.2 節「C API 基本資料結構」中所述。

若要判斷從伺服器傳回的結果集中輸出字串值是否包含二進位或非二進位資料,請檢查結果集中繼資料的 charsetnr 值是否為 63(請參閱第 5.2 節「C API 基本資料結構」)。如果是,則字元集為 binary,表示資料為二進位而非非二進位。這能讓您區分 BINARYCHARVARBINARYVARCHAR,以及 BLOB 類型與 TEXT 類型。

如果您導致設定 MYSQL_FIELD 欄位中繼資料結構的 max_length 成員(透過呼叫 mysql_stmt_attr_set()),請注意結果集的 max_length 值表示結果值最長字串表示的長度,而非二進位表示的長度。也就是說,max_length 不一定對應到使用預處理語句的二進位協定擷取值所需的緩衝區大小。請根據您擷取值的變數類型來選擇緩衝區的大小。例如,包含值 -128 的 TINYINT 欄位可能具有 4 的 max_length 值。但是,任何 TINYINT 值的二進位表示只需要 1 個位元組來儲存,因此您可以提供 signed char 變數來儲存該值,並設定 is_unsigned 以表示值為帶正負號。

如果預處理語句所參照的資料表或檢視表發生中繼資料變更,則系統會偵測到此情況,並在下次執行語句時導致語句自動重新預處理。如需更多資訊,請參閱預處理語句和儲存程式的快取