緣由:由于工作原因呜叫,需要從SQLServer數(shù)據(jù)庫(kù)中同步一部分?jǐn)?shù)據(jù)到mongodb中帐要,用于建模,運(yùn)算落塑。
開(kāi)發(fā)環(huán)境:Windows纽疟,Python3.5.2
開(kāi)發(fā)工具:pycharm2017.1.4
連接SQLServer所用module:pymssql
目標(biāo)數(shù)據(jù)庫(kù)版本:SQLServer2008 編碼為GBK
具體情況:
開(kāi)始連接數(shù)據(jù)庫(kù)的代碼如下
# 連接數(shù)據(jù)庫(kù),獲取游標(biāo)
@staticmethod
def get_sql_connect(host, user, password, database, charset):
if host is None or user is None or password is None or database is None:
raise ConnectionError('連接數(shù)據(jù)庫(kù)的必要參數(shù)為空')
if charset is None:
charset = 'utf8'
sql_conn = pymssql.connect(
host=host,
user=user,
password=password,
database=database,
charset=charset
)
return sql_conn
conn = SynchronizeData.get_sql_connect('.', 'sa', '712604', 'test', 'GB18030')
這里在連接的時(shí)候傳入charset='GBK'憾赁,因?yàn)槟繕?biāo)數(shù)據(jù)庫(kù)編碼是GBK仰挣,在python中如果不帶這個(gè)參數(shù)那么查詢(xún)出來(lái)的中文將會(huì)顯示亂碼。帶上這個(gè)參數(shù)之后一切看起來(lái)沒(méi)毛病缠沈,在執(zhí)行了一段時(shí)間之后發(fā)現(xiàn)會(huì)出現(xiàn)UnicodeDecodeError:'gbk'codec can't decode byte 0x81 in position 18:illegal multibyte sequen這樣的異常膘壶。當(dāng)時(shí)也google了好久错蝴,后來(lái)找了個(gè)靠譜的方案說(shuō)是因?yàn)镚BK的字符不多,于是把GBK換成了GB18030問(wèn)題得到解決颓芭。
但是在導(dǎo)入某個(gè)表的時(shí)候發(fā)現(xiàn)此時(shí)GB18030也報(bào)了上面類(lèi)似的異常顷锰。定位到數(shù)據(jù)以后該字段的類(lèi)型類(lèi)text,里面存儲(chǔ)的是一篇文章,初步估計(jì)是里面的內(nèi)容在python中查詢(xún)之后轉(zhuǎn)Unicode發(fā)生了莫名其妙的錯(cuò)誤亡问。此時(shí)繼續(xù)在google上搜索官紫,絕大部分說(shuō)這個(gè)異常的情況都是在python中打開(kāi)文件,然后解決辦法是在打開(kāi)文件的代碼中加上coding='utf-8',然而我在連接數(shù)據(jù)庫(kù)的時(shí)候不過(guò)不帶charset這個(gè)參數(shù)就會(huì)發(fā)生中文亂碼州藕,帶了吧束世,就會(huì)發(fā)生那個(gè)異常。本來(lái)都打算把數(shù)據(jù)導(dǎo)出成excel床玻,然后通過(guò)mongodbimport去導(dǎo)入了毁涉,奈何數(shù)據(jù)量有點(diǎn)大,昨天這個(gè)導(dǎo)出的過(guò)程持續(xù)了一天也不過(guò)導(dǎo)出了一半不到的數(shù)據(jù)锈死。
今天早上到公司的時(shí)候不死心的又在看這個(gè)問(wèn)題贫堰。忽然想試下把該字段的類(lèi)型改成ntext的形式不知道行不行。(SQLServer中有varchar和nvarchar待牵,text和ntext之分其屏,不知道的請(qǐng)另行百度)。把字段的類(lèi)型改了還是繼續(xù)采用上面的連接缨该,發(fā)現(xiàn)代碼是不報(bào)錯(cuò)了偎行,但是該字段中的所有中文卻消失了,只留下了數(shù)字和符號(hào)贰拿。這很顯然又不行的睦优,于是我試驗(yàn)了下面的代碼
# 連接數(shù)據(jù)庫(kù),獲取游標(biāo)
@staticmethod
def get_sql_connect(host, user, password, database):
if host is None or user is None or password is None or database is None:
raise ConnectionError('連接數(shù)據(jù)庫(kù)的必要參數(shù)為空')
sql_conn = pymssql.connect(
host=host,
user=user,
password=password,
database=database
)
return sql_conn
conn = SynchronizeData.get_sql_connect('.', 'sa', '712604', 'test')
激動(dòng)人心的事情發(fā)生了:中文不亂碼了壮不,而且字段中的內(nèi)容也沒(méi)丟失。問(wèn)題到這里似乎就可以解決了皱碘。接下來(lái)的情況就因人而異了:
在修改表字段的時(shí)候發(fā)現(xiàn)有的字段有索引询一,導(dǎo)致修改類(lèi)型失敗。于是問(wèn)題轉(zhuǎn)變成能不能在查詢(xún)的時(shí)候把類(lèi)型給替換掉癌椿。很顯然SQLserver還是可以完成這樣的功能的: CAST()
于是把我查詢(xún)的select * from table 改成 select cast(中文內(nèi)容的字段 as ntext) from table (如果該字段是varchar則 as后面是 nvarchar)健蕊,問(wèn)題到這才算完美解決