none
透過 odbc 讀取舊 mysql 資料庫上資料,編碼明明是utf8卻要用big5去讀取的奇怪問題 RRS feed

  • 問題

  • 各位好

    公司有一台 mysql server,裡面所用的編碼,從資料庫、資料表、欄位,以及裡面存放的資料,均確定使用 utf8 格式,可是我透過 myodbc 3.51 ,在 vb2005 中以 Odbc.OdbcConnection、Odbc.OdbcDataAdapter、DataTable 做處理,怎麼讀取出來都是亂碼,結果最後試出來要先透過 OdbcCommand 送出 SET NAMES 'big5'  (用 SET NAMES 'utf8' 也是亂碼) 這一段 SQL 命令後才可以正常讀取,請問這該怎麼解決呢?

     

    程式如下:

     

    1.我自訂的資料庫連結類別

    Code Snippet

        Public Class DBConnect
            Dim Conn As New Odbc.OdbcConnection
            Sub New()
            End Sub

            '建立連線
            Function Connect(ByVal strServerName As String, ByVal strDatabaseName As String, ByVal strUserName As String, ByVal strPassword As String) As Integer

                '建立連線字串
                Dim ConnectString As String = _
                "DRIVER={MySQL ODBC 3.51 Driver};" & _
                "SERVER=" & strServerName & _
                ";DATABASE=" & strDatabaseName & ";" & _
                "USER=" & strUserName & ";PASSWORD=" & strPassword & ";Port=3306;"

                '開啟連線
                Conn.ConnectionString = ConnectString

                '開啟
                Try
                    Conn.Open()
                    Return 1
                Catch ex As Exception
                    MsgBox("與資料庫連線時發生錯誤" & vbCrLf & ex.Message, , "錯誤")
                    Return 0
                End Try

            End Function

            '關閉與伺服器連線
            Sub Close()
                On Error Resume Next
                Conn.Close()
            End Sub

            '建立 DataTable
            Function GetDataTable(ByVal sqlStr As String) As DataTable

                '取出資料()
                Dim da As New Odbc.OdbcDataAdapter(sqlStr, Conn)

                '將資料填入 DataTable
                Dim dt As New DataTable
                da.Fill(dt)
                Return dt

            End Function

            '執行變更
            Function ExeCommand(ByVal sqlStr As String) As Integer

                Dim cm As New Odbc.OdbcCommand(sqlStr, Conn)
                Return cm.ExecuteNonQuery

            End Function

        End Class

     

     

     2.我執行的內容   

    Code Snippet

    Dim bb As New DBConnect
     If bb.Connect("dbserver.xxx.com.tw", "testdb", "test", "123") = 0 Then End

     

    '告訴資料庫所要使用編碼
     bb.ExeCommand("SET NAMES 'big5'")

    Dim Sqlstr As String

    sqlstr = "SELECT * FROM Attend LIMIT 50"

    dt = bb.GetDataTable(Sqlstr)

     

    DataGridView1.DataSource = dt

    bb.Close()

     

     

    2007年3月30日 下午 04:25

解答

  • 1. 最好使用 MySQL Connector for .NET

    2. MyODBC Driver 會有已知的編碼問題:http://tlcheng.spaces.live.com/blog/cns!145419920BFD55A7!763.entry

    2007年3月30日 下午 11:49
    版主
  • MySQL Connector for .NET 1.0 也是一樣。

     

    前陣子有網友說新版的 MySQL Connector for .NET 5.0 已經解決這個問題,你可以搜尋看看。

    2007年3月31日 上午 01:48
    版主
  • 你可以去看一下 MyOdbc 的原始碼。

     

    我的理解是 socket 傳輸內容的 bytes 陣列採用 big5 編碼方式傳輸。

     

    理論上來說,是可以去改 MyOdbc 讓他將 utf8 透過 MultiByteToWideChar 轉回 unicode 餵給其他程式,所以我想有很多非官方版本的 MyOdbc 應該類似這樣改出來的吧...

     

    這邊只是傳輸過程採用的編碼,與資料庫內指定的編碼沒有直接相關,我自己指定 MySQL 用 ucs2 ,也就是直接用 Unicode 。而 VB6/VBNET 的字串在記憶體中都是 Unicode ,所以完全不會影響程式架構與資料庫架構。你認為會影響應該是你會錯意了。若是網頁系統,不改編碼沒關係,只是有可能發生日韓簡罕會變成空格,若要改網頁編碼,直接改 web.config 指定為 big5 ,則日韓簡罕會被編為 &#nnnnn; 存入資料庫,在網頁應用上就不受影響。

     

    另外我對於 MySQL 使用 utf-8 時,宣告字串 n 指的是位元數還是字串長度滿存疑的,所以我不使用預期之外的東西,所以 MySQL 內部編碼我一律採用 ucs2...

    2007年4月2日 上午 01:13
    版主
  • 回報目前情況:

     

    試出以下組合,可以繁/簡/日並存並可寫/讀正常

     

    VB2005 + Connector/NET 5.0.6 (MyODBC 測試沒有辦法使用 utf8)

     MySQL 4.1.15   

     

    確認 MySQL Server 為以下設定 (必備條件)

    'character_set_client', 'utf8'

    'character_set_connection', 'utf8'

    'character_set_database', 'utf8'

    'character_set_results', 'utf8'

    'character_set_server', 'utf8'

    'character_set_system', 'utf8'

     

    資料表的編碼無所謂,但要存放多國語系的欄位則必須指定為 utf8 (必備條件)

     

    這是我的測試程式碼:

    (已省略不必要程式碼)

     

    Code Snippet

           Dim Sqlstr As String

     

            '寫入
            conn.ExeCommand("SET NAMES 'utf8'")
            Sqlstr = "UPDATE Service_Form SET Service_Form_State = '" & _
            "繁:測試的 簡:相互转换 日:全国の桜名所 ' LIMIT 10 "
            conn.ExeCommand(Sqlstr)


            '秀出來
            conn.ExeCommand("SET NAMES 'utf8'")
            Sqlstr = "SELECT * Service_Form WHERE LIMIT 10 "
            dt = conn.GetDataTable(Sqlstr)
            DataGridView1.DataSource = dt

     

     

     

    補充1:

    若是像這樣 SELECT Service_Form_State AS 狀態 Service_Form WHERE LIMIT 10 的語法, AS 後面的中文出來仍是亂碼,但資料內容則無問題。研判為 Connector/Net 仍有些問題。

     

    補充2:

    在 Server 已全部如上所示設定為 utf8、資料內容與欄位也為 utf8,ODBC 有以下情形:

    MyODBC 3.51:被 Server 拒絕連線

    MyODBC 5.0:可以連線,但取回資料均是亂碼,不論用 big5、utf8 讀取均無解。

    2007年4月2日 上午 06:48
  • 一開始忘了說...

     

    建議你先去 MySQL 官方網站看看授權協議,很多狀況是要購買商用授權,不能免費使用,算一算價格,你會覺得用 SQL Server 還比較方便與划算。

     

    不過一開始小朱給的網誌裡面就有說到 MySQL 授權問題,所以忘了說這句。

     

    公司若是有在內地設廠的,更要注意,去年 8 月中國北京那邊有個公司,據說是 MySQL 在中國的分公司,那個單位的業務經理在很多簡體留言板有聲明 MySQL 的商用授權問題,號稱是他們會開始抓,說的很張狂,所以若是用免費版本的話... 最好確認授權... 因為 MySQL 商用授權最低等級版本起跳每年每台電腦 595 美金,用 5 年匯差 30 元台幣來算,就要 9 萬元...

    2007年4月2日 上午 08:13
    版主

所有回覆

  • 1. 最好使用 MySQL Connector for .NET

    2. MyODBC Driver 會有已知的編碼問題:http://tlcheng.spaces.live.com/blog/cns!145419920BFD55A7!763.entry

    2007年3月30日 下午 11:49
    版主
  • MySQL Connector for .NET 1.0 也是一樣。

     

    前陣子有網友說新版的 MySQL Connector for .NET 5.0 已經解決這個問題,你可以搜尋看看。

    2007年3月31日 上午 01:48
    版主
  • 我用 MySQL Connector for .NET (1.0) 沒有這個問題 ...
    不過既然 5.0 出來了,就用 5.0 吧
    2007年3月31日 上午 01:55
    版主
  • 若是已指定 SET NAMES  'big5' 請問所取回的文字是否代表已被轉為 big5 ?

     

    因此牽涉到整個程式架構,因此甚是煩惱 ><"

    2007年4月2日 上午 12:59
  • 你可以去看一下 MyOdbc 的原始碼。

     

    我的理解是 socket 傳輸內容的 bytes 陣列採用 big5 編碼方式傳輸。

     

    理論上來說,是可以去改 MyOdbc 讓他將 utf8 透過 MultiByteToWideChar 轉回 unicode 餵給其他程式,所以我想有很多非官方版本的 MyOdbc 應該類似這樣改出來的吧...

     

    這邊只是傳輸過程採用的編碼,與資料庫內指定的編碼沒有直接相關,我自己指定 MySQL 用 ucs2 ,也就是直接用 Unicode 。而 VB6/VBNET 的字串在記憶體中都是 Unicode ,所以完全不會影響程式架構與資料庫架構。你認為會影響應該是你會錯意了。若是網頁系統,不改編碼沒關係,只是有可能發生日韓簡罕會變成空格,若要改網頁編碼,直接改 web.config 指定為 big5 ,則日韓簡罕會被編為 &#nnnnn; 存入資料庫,在網頁應用上就不受影響。

     

    另外我對於 MySQL 使用 utf-8 時,宣告字串 n 指的是位元數還是字串長度滿存疑的,所以我不使用預期之外的東西,所以 MySQL 內部編碼我一律採用 ucs2...

    2007年4月2日 上午 01:13
    版主
  • 謝謝您

     

    剛剛測試了一下,我先用 MySQL Query Browser 去修改其中欄位的資料為簡體文字,在 Query Browser 簡繁體並存顯示都很正常。

     

    程式中則發生以下情況:

     

    ("SET NAMES 'big5'")

    可以送出含中文字的 sql string,但取回的資料無法顯示簡體,

    UPDATE 的字串中若簡繁並存,簡體變亂碼,繁體正常

     

     

     

    ("SET NAMES 'utf8'")

    可以送出含中文字的 sql string,但是存入的中文字全部變成亂碼。

    select 取回的資料可以顯示簡體,但 select 的字串中若有中文 (如: SELECT * FROM test WHERE Name = '測試' ) 也會出現錯誤

     

    2007年4月2日 上午 04:01
  • 回報目前情況:

     

    試出以下組合,可以繁/簡/日並存並可寫/讀正常

     

    VB2005 + Connector/NET 5.0.6 (MyODBC 測試沒有辦法使用 utf8)

     MySQL 4.1.15   

     

    確認 MySQL Server 為以下設定 (必備條件)

    'character_set_client', 'utf8'

    'character_set_connection', 'utf8'

    'character_set_database', 'utf8'

    'character_set_results', 'utf8'

    'character_set_server', 'utf8'

    'character_set_system', 'utf8'

     

    資料表的編碼無所謂,但要存放多國語系的欄位則必須指定為 utf8 (必備條件)

     

    這是我的測試程式碼:

    (已省略不必要程式碼)

     

    Code Snippet

           Dim Sqlstr As String

     

            '寫入
            conn.ExeCommand("SET NAMES 'utf8'")
            Sqlstr = "UPDATE Service_Form SET Service_Form_State = '" & _
            "繁:測試的 簡:相互转换 日:全国の桜名所 ' LIMIT 10 "
            conn.ExeCommand(Sqlstr)


            '秀出來
            conn.ExeCommand("SET NAMES 'utf8'")
            Sqlstr = "SELECT * Service_Form WHERE LIMIT 10 "
            dt = conn.GetDataTable(Sqlstr)
            DataGridView1.DataSource = dt

     

     

     

    補充1:

    若是像這樣 SELECT Service_Form_State AS 狀態 Service_Form WHERE LIMIT 10 的語法, AS 後面的中文出來仍是亂碼,但資料內容則無問題。研判為 Connector/Net 仍有些問題。

     

    補充2:

    在 Server 已全部如上所示設定為 utf8、資料內容與欄位也為 utf8,ODBC 有以下情形:

    MyODBC 3.51:被 Server 拒絕連線

    MyODBC 5.0:可以連線,但取回資料均是亂碼,不論用 big5、utf8 讀取均無解。

    2007年4月2日 上午 06:48
  • 一開始忘了說...

     

    建議你先去 MySQL 官方網站看看授權協議,很多狀況是要購買商用授權,不能免費使用,算一算價格,你會覺得用 SQL Server 還比較方便與划算。

     

    不過一開始小朱給的網誌裡面就有說到 MySQL 授權問題,所以忘了說這句。

     

    公司若是有在內地設廠的,更要注意,去年 8 月中國北京那邊有個公司,據說是 MySQL 在中國的分公司,那個單位的業務經理在很多簡體留言板有聲明 MySQL 的商用授權問題,號稱是他們會開始抓,說的很張狂,所以若是用免費版本的話... 最好確認授權... 因為 MySQL 商用授權最低等級版本起跳每年每台電腦 595 美金,用 5 年匯差 30 元台幣來算,就要 9 萬元...

    2007年4月2日 上午 08:13
    版主
  • 公司也有在評估這些項目,不過 SQL Server 要達到我們需要的功能,報價要三十幾萬,實在不划算..

    不然我也是希望配 SQL Server,省事又方便。

     

    不過目前 utf8 的問題至少已經解決一半了,也謝謝您的幫忙 ^^

    我的 VB 網站也倒了很久了,不曉得您是否還記得 "三優資訊網"

    2007年4月2日 下午 12:47
  • 你是站長鄭郁霖?
    2007年4月2日 下午 01:00
    版主
  • 是的!

    沒想到您還記得,真是太榮幸了..

    2007年4月3日 上午 02:52
  • 我有看了大家的POST .   MyODBC Driver 會有已知的編碼問題:http://tlcheng.spaces.live.com/blog/cns!145419920BFD55A7!763.entry

     

    最近也是為了 同時顯示簡繁體 一直很傷腦筋

    我是用ASP來連接 MySQL , 測試結果是這樣

    Myodbc 3.51 無法完整讀取及儲存UTF8字元, 例如...總..和...总..要同時寫入資料庫就寫不進去

    MyOdbc v5  卻可以寫入 UTF8 字元, 但是卻讀不出來,  不管怎樣,總算有進步囉

    我有在MySQL 官網論壇發了文章, 可是討論到最後 好像又卡到 UTF8的問題,就沒解了

    所以 PHP + MySQL 似乎 是比較好的組合

    因為 在 PHPadmin 中  讀取修改新增UTF8 的字元,  完全沒有問題

    唉, 我快要放棄了,  只能等待官方能夠有解決的方法

     

    http://forums.mysql.com/read.php?37,139219,139219#msg-139219

    2007年4月23日 下午 06:06
  • MySQL 官網的部份你可以先搜尋以前的討論跟 bug 回報,你會發現關於這部份的討論很多人提過,然後就放到爛掉了...

     

    我自己也在官網提過,不過也沒下文。

     

    未來應該是比較可以期待的,去年八月 MySQL 在北京成立營運中心以後,應該是會加強編碼這塊的處理。我說「應該」...

     

    目前還是優先選用 SQL Server 2005 ,退可退到免費版本 Express ,進可前進企業版...

    2007年4月24日 上午 02:28
    版主