RDSSQLSERVER解決中文亂碼問題

風移發表於2016-11-28

問題引入

這天老鳥又開始糾纏著菜鳥:“菜鳥啊,我們最近遇到一個RDS SQL Server 2008 R2的奇怪的問題,我們的生僻字寫入到RDS SQL Server中,查詢結果展示出來是亂碼呀?你去解決下這個問題吧。”。
“可是,鳥哥,我最近在做關於SQLTest的系列文章啊,暫時抽不出。。。。。。”。
“那個暫時先放放,這個比較緊急,儘快,立刻,馬上去覆盤並解決掉,Understand?”。還沒等菜鳥說完,老鳥已經迫不及待的發號施令了。

覆盤分析

看到老鳥為這事著急上火的樣子,菜鳥已經意識到問題的嚴重性,於是放下手中的活,趕緊投入到這個問題的覆盤分析中來。

覆盤

經過一番翻雲覆雨的研究後,菜鳥拿出了覆盤的例子來,參見下面的程式碼:

use tempdb
go
IF OBJECT_ID(`#temp`, `U`) IS NOT NULL
    DROP TABLE #temp
GO

create table #temp(
firstName varchar(10)
)

insert into #temp
select `䅇`
union all
select `庫`
;

select * from #temp

查詢結果如下圖所示:
01.png

分析

從查詢結果展示來看,生僻字“䅇 (su)” 的確顯示為亂碼問號(?)。菜鳥終於覆盤了老鳥說得場景,但是他還是高興不起來。難道RDS SQL Server 2008R2真如鳥哥所說,對生僻字不支援嗎?高階大氣上檔次的阿里雲RDS SQL Server不至於吧?隨著研究的深入,菜鳥漸漸的找到問題的根本原因:
SQL Server是使用Unicode編碼的資料型別來支援中文的,比如:NCHAR, NVARCHAR等資料型別,類似的語言還有拉丁語系,和包含中文在內的亞洲語言。所以,要解決這問題,我們的資料型別選擇就必須是Unicode編碼的資料型別,很顯然覆盤例子中的資料型別VARCHAR選擇錯誤,我們只需要將這個資料型別修改為NVARCHAR,即可解決問題了。

解決問題

在正確分析了問題所在以後,解決問題就變得很簡單了,參見下面的測試程式碼:

use tempdb
go
IF OBJECT_ID(`#temp`, `U`) IS NOT NULL
    DROP TABLE #temp
GO

create table #temp(
firstName nvarchar(10)
)

insert into #temp
select N`䅇`
union all
select N`庫`
;

select * from #temp

測試結果展示
02.png
從結果展示來看,生僻字“䅇 (su)”已經可以成功展示出來了,這裡需要特別強調兩點,否則很有可能展示出來還是亂碼:

  • 資料型別選擇請務必使用Unicode編碼格式的型別,這裡選擇的是NVARCHAR。
  • 在向Unicode編碼格式的資料型別插入資料時,需要使用前置詞N。N前置詞代表的是 SQL-92標淮中的國家語言,且N必須為大寫。如果您沒有在Unicode字串常數前面加上N做為前置詞,則SQL Server會在使用字串前,先將其轉換成目前資料庫的非Unicode 字碼頁。

寫在最後

至此,菜鳥成功覆盤並解決了RDS SQL Server 2008 R2遭遇生僻字亂碼的問題。又開始回過頭來繼續SQLTest系列,革命尚未成功,同志還需努力。


相關文章