整點編碼字符串是你不是只是存儲位,你存儲字符串。根據Oracle數據庫,Oracle的Choosing a character set文檔準確解釋了這意味着什麼。
甲單字節編碼只知道如何表示(至多)256個不同的字符。如果你給它一個不同的字符,它不能代表它。它應該做什麼呢?
你的建議是,它應該採取一些其他編碼的表示,並假裝字節是在其自己的編碼字符。這不僅在概念上沒有意義,而且實際上也行不通 - 事實上,這正是mojibake的意義所在。
要採取的具體的例子,你有一個WE8MSWIN1252(大致相同編碼的Python調用CP1252)字符串列。你想存儲字符串'中文'
。這沒有cp1252,但是它有一個UTF-8,它是'\xe4\xb8\xad\xe6\x96\x87'
。
那麼,如果你只是存儲了UTF-8字節好像他們是cp1252字符?那麼,這取決於數據庫如何定義代碼頁1252。最後兩個字節在原始代碼頁1252中不是有效的字符,但當前的Windows代碼頁1252確實將它們映射到字符。因此,如果數據庫按照IBM規則運行,它應該給你一個錯誤,或者用「無效字符」表示法替換字節(至少對於有這種事情的編碼); *如果它試圖模擬Windows,它。應該允許它**
爲了避免這個問題,讓我們把它簡單:如果您選擇什麼完整的256個字符的1 - 拉丁語系編碼?這會欺騙它讓你存儲數據。然後你會存儲字符串'ä¸æ'
或'ä¸\xadæ–‡'
或類似的東西。這看起來不太有用。你可以編寫一個應用程序,這樣做是有道理的(因爲你知道你將通過Latin-1 mojibake重新編碼爲UTF-8到每一邊的真實字符串),但在這種情況下,爲什麼你要使用一個字符串首先?只需使用二進制列,並跳過整個Latin-1部分,應用程序就知道二進制數據表示UTF-8,而不是讓應用程序知道看起來像Latin-1的必須被記錄爲UTF-8有用。
甚至更簡單,只需用UTF-8列,或停止嘗試東亞文本存放在CP1252列...
*請參閱the docs甲骨文如何解釋替換字符,這比你想象的要複雜一些,與Python不一樣。
**您的數據庫調用的編碼WE8MSWIN1252
的事實似乎暗示它應該是使用Windows定義;它將它們轉換爲0xBF的事實意味着它不是這樣做的。這很可能是合理的,因爲「MSWIN」意味着「MS Windows 3.1」或者地獄,即使是「MS Windows 1.0」,但我真的不知道。無論如何,正如下一段所解釋的那樣,這並不重要。如果要查看在「代碼頁1252」的任何含義下不應該合法的字符會發生什麼情況,請參閱試用'東京'
,即UTF-8中的'\xe6\x9d\xb1\xe4\xba\xac'
,並且0x9D在cp1252中有意留空。
如果數據庫能夠執行字符集轉換,它必須保證進入的字符屬於您聲明的字符集。但'\ x96'和'\ xe7' [看起來是有效的字符](http://en.wikipedia.org/wiki/Windows-1252#Code_page_layout),所以問題必須存在於一些微妙的交互中。 – 2014-09-25 21:21:50
_(96)‡(87)。你是否同意它不應該改變每個邏輯的輸入?讓Charset承擔其他事情。我沒有問題,因爲我可以在渲染時強制執行UTF-8。我可以看到第一個角色保持完美,因此期待第二個角色也這樣做。我至少希望能夠閱讀這個流,並強制執行一個utf-8來使其工作!我需要更深入地瞭解這一點,但至少你能澄清一下,如果你認爲你認爲這不應該純粹是在邏輯基礎上發生,並需要更多的研究?它更多地瞭解這一切。 – Nishant 2014-09-25 22:38:52
數據庫不能只留下一些東西,因爲它保證了字符集轉換的能力。實際上,它可能會在進出途中進行轉換,併爲內部存儲使用一些不相關的字符集以保持一致性。無論它是否應該在這種特殊情況下工作都是無關緊要的,因爲abarnert已經提供了一個保證失敗的例子。 – 2014-09-25 22:48:31