6.2.2 C API Prepared Statement 型別轉換

Prepared Statement 使用用戶端 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 不一定對應於使用 prepared statement 的二進制通訊協定擷取值所需的緩衝區大小。請根據您擷取值的變數類型選擇緩衝區的大小。例如,包含值 -128 的 TINYINT 資料行可能具有 4 的 max_length 值。但任何 TINYINT 值的二進制表示形式僅需要 1 個位元組進行儲存,因此您可以提供 signed char 變數來儲存該值,並設定 is_unsigned 來表示值為帶符號的。

會偵測到 Prepared Statement 所參考之表格或檢視表的中繼資料變更,並在下次執行時自動重新準備陳述式。如需更多資訊,請參閱 Prepared Statement 和儲存程式的快取