隨着時代的進步,社會的發展,各種技術層出不窮五花八門亂七八糟數不勝數(寫作文呢!!!)
不扯廢話,簡單而言,很多公司都會同時使用多種數據庫,因此數據在不同數據庫之間導入導出就成為一個讓人蛋疼的問題,對於周期行的需求,可以開發專門的程序處理,但是對於偶爾不確定性的需求,就到了需要DBA獻身的時候啦,當需要將MySQL數據導入到SQL Server中時,該怎么搞呢?
當然使用工具最簡單,但是我就忽略工具!!!
在MySQL中創建測試數據:
create table tb001(c1 int auto_increment primary key,c2 varchar(2000)); insert into tb001(c2) select 'abc\r\n'; insert into tb001(c2) select '你好啊\r\n'; insert into tb001(c2) select '你好啊\n'; insert into tb001(c2) select '雙引號"'; insert into tb001(c2) select '全角雙引號“'; insert into tb001(c2) select '單引號'''; insert into tb001(c2) select '全角單引號’';
##=====================================================================##
使用mysqldump來導出與MS SQL SERVER兼容的INSERT 語句:
mysqldump --host='192.168.166.169' --port=3358 --user='mysql_admin' --password='mysql@Admin@Pwd' --skip-add-locks --compatible=mssql --complete-insert --compact --extended-insert=false --default-character-set=utf8 -t --databases 'test' --table 'tb001' >/tmp/t4.sql
上面腳本的一些注釋說明:
--compatible=mssql ##導出的SQL與MS SQL Server兼容
--complete-insert ##導出的INSERT語句包含列名
--compact ##采用精簡模式,不輸出各種MySQL信息
--extended-insert=false ##采用一行數據一條INSERT的方式
--default-character-set=utf8 ##指定導出的字符集
-t ##-t表示只導出數據,-d表示只導出數據結構
--databases 'test' ##數據庫名稱
--table 'CityMatchup' ##表名
導出結果為:
INSERT INTO "tb001" ("c1", "c2") VALUES (1,'abc\r\n'); INSERT INTO "tb001" ("c1", "c2") VALUES (2,'你好啊\r\n'); INSERT INTO "tb001" ("c1", "c2") VALUES (3,'你好啊\n'); INSERT INTO "tb001" ("c1", "c2") VALUES (4,'雙引號\"'); INSERT INTO "tb001" ("c1", "c2") VALUES (5,'全角雙引號“'); INSERT INTO "tb001" ("c1", "c2") VALUES (6,'單引號\''); INSERT INTO "tb001" ("c1", "c2") VALUES (7,'全角單引號’');
對於列名用雙引號的問題,可以使用SET QUOTED_IDENTIFIER ON 來處理,也可以使用SQLCMD加-I參數來處理
但是對文本中的單引號就無解了,MySQL中使用"\"來作為轉義符,而SQL Server中使用兩個單引號來表示一個單引號。
MySQLdump可以將數據導成INSERT語句,並提供配置兼容其他數據庫的參數,但由於不同數據庫轉義字符不同,因此即使使用compatible=mssql也不能保證導出的腳本能在SQL Server中正常執行。
##===========================================================================##
使用SELECT INTO OUTFILE來導出數據
SELECT * INTO OUTFILE '/tmp/tb001.txt' FIELDS TERMINATED BY '||--||' LINES TERMINATED BY '||==||' FROM test.tb001;
在Linux下看到的是這樣:

雖然有點亂,但是忍啦!
然后下載文件,使用notepad++打開,選擇“格式”>> "轉為ANSI編碼格式" ,然后另存為新文件,在SQL Server中使用BULK INSERT來導入:
CREATE TABLE tmp_tb001(id NVARCHAR(2000),c1 NVARCHAR(2000)) GO BULK INSERT tmp_tb001 FROM 'D:\tb002.txt' WITH(FIELDTERMINATOR='||--||', ROWTERMINATOR='||==||' ) GO SELECT * FROM tmp_tb001
也可以使用SQL Server的導入導出工具來處理,主要修改分隔符。
注意使用SELECT INTO OUTFILE導出文件時,NULL值被表示為\N,而\N在導入SQL Server時會被當初字符串“\N”來處理,因此建議先建立一個完全由NVARCHAR類型列組成的表來“暫存”導入的時候,然后經過數據清理后再導入正式表中,對於懶與一列一列折騰的人來說,可以拼下SQL來獲取表的所有列轉換:
SELECT 'CASE WHEN ['+T1.name+']=''\N'' THEN NULL ELSE ['+T1.name+'] END AS ['+T1.name+'],' FROM sys.all_columns T1 WHERE T1.object_id=OBJECT_ID('tmp_tb001')
由於我們強行將\N當成NULL來轉換,難免會造成誤傷,將真實數據就為’\N‘的值變為NULL,因此導完數據后檢查是必須的。
最后語句為:
SELECT CASE WHEN [id]='\N' THEN NULL ELSE [id] END AS [id], CASE WHEN [c1]='\N' THEN NULL ELSE [c1] END AS [c1] FROM tmp_tb001
執行結果為:

##=======================================================================##
導出INSERT腳本存在轉義字符單引號的問題,同時導出數據不包含GO,在需要大量數據導入到SQL SERVER時存在嚴重的性能問題,可以嘗試參考本人的《Powershell--批量拆分SQL語句為事務並批處理》來處理,但也是問題多多。
而導出文件然后導入的方式,需要對文件進行一次轉換,文件較大時notepad++可能無法打卡,UE能稍微給力點,但面對好幾個G的文本文件也是無力回天,同時NULL值處理也需要慎重對待。
##========================================================================##
好啦,是時候上妹子啦。

