我有具有索引VARCHAR(10) NOT NULL COLLATE 'utf8mb3_general_ci'型別的 MariaDB 表。我在 Go 中有一個字串,如果它更長,我將其剪切為 10 個字符,以插入/更新此表。我把字串剪成:
if len(value) > 10 {
value = value[:10]
}
現在我遇到了一個以字符結尾的字串的問題?。MariaDB 拋出錯誤:Error 1366: Incorrect string value: '\\xC5'. 查找 unicode 表,這個字符表示為\xc5\xa1這讓我相信字串的切割以某種方式使字串無法被資料庫消化?
我想避免在我的代碼中處理 utf8/unicode,因為這需要遍歷所有資料庫方法并處理所有字串。而且我不認為這是必要的,因為我以前從未需要它。所以我認為問題出在其他地方,但不確定在哪里。
我試圖將排序規則切換到,utf8mb4_general_ci但這也無濟于事。
有趣的是,如果我直接使用 HeidiSQL 編輯列,則字串保存得很好。這讓我相信這可能是驅動程式問題。我github.com/go-sql-driver/mysql一如既往地使用 . 所以我不會期待問題,但是,誰知道......
uj5u.com熱心網友回復:
這讓我相信字串的切割以某種方式使資料庫無法消化字串?
如果您的程式有任何機會處理多位元組字符,那么通過子切片value[:10](并len為此測量長度)來切割字串始終是錯誤的。這是因為對字串進行索引是對其位元組進行操作,這可能是也可能不是多位元組編碼的一部分。
如您所見,該字符?以 UTF-8 編碼為\xc5\xa1. 如果這兩個位元組出現在您的value字串中的索引處9,并且10您的索引運算式[:10]損壞了資料。
字符集utf8mb3僅utf8mb4將允許的 UTF-8 范圍分別限制為 3 位元組和 4 位元組字符,但從\xc5一開始就不是有效的 UTF-8,因此無論哪種方式都被拒絕。
在 MariaDB 中,具有資料型別的列對字符VARCHAR(N)進行計數(由排序規則指定)。您想在第十個字符處剪切字串,而不是在第十個位元組處。value
我想避免在我的代碼中處理 utf8/unicode
您已經通過將 MariaDB 排序規則宣告為utf8mb3. 將代碼中的輸入資料正確處理為 UTF-8 是合乎邏輯的。要在第 n 個字符處剪切(或者rune,在 Go 中表示 Unicode 代碼點),您可以使用以下內容:
// count the runes
if utf8.RuneCountInString(value) > 10 {
// convert string to rune slice
chars := []rune(value)
// index the rune slice and convert back to string
value = string(chars[:10])
}
這不會破壞 UTF-8 編碼,但是請記住,它會進行更多的分配,并且不考慮組合字符,例如當200D涉及連接器時。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/417206.html
標籤:
