2011-10-26 58 views
2

在一個數據庫中,我將不得不姓名及在UTF8和散列存儲在latin1_bin。我打電話給SET NAMES utf8,但我注意到,當我試圖閱讀它們(我能夠寫得很好)時,它破壞了latin1字段。這是奇怪的,因爲如果我理解正確的查詢是隻有約發送數據到服務器,而不是接收它。混合UTF8和latin1_bin領域與PHP

phpMyAdmin也顯示損壞的數據。

關於我可能會做錯什麼的線索?

(使用MAMP 1.9.6)

編輯:this答案指定這也是用於將數據發送回客戶端的字符集。我感到困惑:指定字符集的字符集有什麼意義?

編輯: 從列定義中摘錄:從查詢

`tok` char(64) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, 
    `sal` char(16) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, 
... 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_roman_ci ; 

摘錄:

SELECT tok,sal FROM user WHERE id=4 LIMIT 1 

INSERT INTO user (tok, sal) VALUES (x'1387ea0c22277d3000bd23241c357e3a9ba45a2e28f50581d63a73bf785a7458a95cca4de27d0a86588f5bdfa94415d6a255c2c0379ebc2f00dacba03ae6b866', x'8fca28a592c29f245ff0a3ba5f97420c') 
+0

如何在您的哈希列定義,什麼你的讀/寫的查詢是什麼樣子? – Jon

+0

@Jon:使用列和查詢摘錄進行更新 –

+0

在閱讀時如何處理傳入值?這應該工作:'echo bin2hex(iconv(「UTF-8」,「ISO-8859-1」,$ sal))'。 – Jon

回答

3

你應該改變你的表定義中使用MySQL的BINARY類型,這是這類數據的完美契合:

的BINARY和VARBINARY類型類似於CHAR和VARCHAR,不同 它們包含二進制字符串而不是非二進制字符串。那 是,它們包含字節串而不是字符串。這 意味着它們沒有字符集,根據值中字節的數字值進行排序和比較 。

列定義將成爲:

`tok` binary(64) NOT NULL, 
`sal` binary(16) NOT NULL, 
-1

set names ...只設置的字符集的連接的(只在客戶端側的!)用於發送和接收數據。它與數據庫中字段的編碼無關!它僅與用作數據庫客戶端的編碼有關,例如在PHP中。數據庫引擎將始終將表中的編碼之間的編碼轉換爲在set names ...查詢中指定的編碼。

所以在表格定義中,您只需指定每個字段的編碼,並且您不會像使用set names ...命令那樣更改任何內容 - 它與以前一樣保持不變。

+0

我不明白:我怎樣才能混合不同的編碼呢? –

+0

@lohoris,只需在'create table'或'alter table'命令中指定編碼即可。然後,在客戶端連接期間,2種不同的編碼將被轉換爲'set names ...'中指定的連接編碼(這意味着連接編碼必須能夠包含所有使用的編碼,所以如果你有非常不同的編碼你可能需要使用utf-8作爲連接編碼)。 – TMS

+0

爲什麼這篇文章downvoted?我使用這種方法多年,它的工作原理。這是在投票時留下評論的好文化的一部分。 – TMS

-1

離開SET NAMES上,並且INSERT查詢完好,我改變了SELECT查詢:

SELECT BINARY(tok) AS tok, BINARY(sal) AS sal FROM user WHERE id=4 LIMIT 1 

即我澆鑄散列字段爲二進制。

雖然這個工作,我會離開這個開放的情況下,有人提供了一個(也許更正確?)替代。

+1

我認爲表格定義中的'sal binary(16)NOT NULL'會更正確,但這不會影響到這裏。你能檢查一下嗎?如果它解決了這個問題,那就是恕我直言「正確的解決方案。 – Jon

+0

@Jon:是的,工作,謝謝:)(你會發布它作爲答案,所以我可以接受它?) –

+0

添加了答案。 – Jon