qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          SQL批量復(fù)制命令的六個(gè)陷阱

           批量復(fù)制工具(BCP)是SQL Server主要的命令行工具之一,使用非常方便,它也是SQL Server導(dǎo)入導(dǎo)出海量數(shù)據(jù)的方式。但是DBA應(yīng)注意BCP存在幾項(xiàng)限制,本文作者通過自身經(jīng)歷總結(jié)了一些主要的問題表現(xiàn)。

            1、沒有對(duì)UTF-8的支持

             SQL Server有對(duì)Unicode的本地支持,使用過nvarchar和ntext字段類型的任何人都知道。它通過映射每個(gè)字符為雙字節(jié)實(shí)體來內(nèi)部處理 Unicode。如果你只是處理SQL Server實(shí)例之間的數(shù)據(jù),那么不會(huì)有任何問題,因?yàn)樗鼈兌家韵嗤姆绞酱鎯?chǔ)。

            不過,如果你 試圖使用BCP從把Unicode導(dǎo)出為UTF-8的數(shù)據(jù)來源導(dǎo)入數(shù)據(jù),那事情就有點(diǎn)復(fù)雜了。UTF-8是Unicode的一種子變體,專門設(shè)計(jì)支持與八 位ASCII文本的向后兼容,所以默認(rèn)使用八位ASCII編碼的網(wǎng)頁(yè)、電子郵件和其它格式可以用于存儲(chǔ)Unicode數(shù)據(jù)。

            如果你從UTF-8源導(dǎo)出數(shù)據(jù),不要指望對(duì)這些數(shù)據(jù)使用BCP;它一直不支持UTF-8。你必須考慮數(shù)據(jù)問題,以完整雙字節(jié)Unicode導(dǎo)出使數(shù)據(jù)形成可接受格式。具有諷刺意味的是,另一個(gè)普通的編碼可以通過“-C”開關(guān)(ISO 1252,ANSI/微軟公司Windows)被BCP接受。不過,就整體而言,你最好把數(shù)據(jù)導(dǎo)出為雙字節(jié)Unicode,以保持對(duì)BCP的最大兼容性,尤其是如果你處理的數(shù)據(jù)可能包含與ASCII不兼容的字符。

            2、注意導(dǎo)出的行順序

             使用BCP通過查詢導(dǎo)出的數(shù)據(jù)對(duì)于導(dǎo)出順序遵守相同的規(guī)則,會(huì)應(yīng)用于任何其它情況的查詢。換句話說,如果你的查詢沒有明確的“ORDER BY”從句,你獲得的數(shù)據(jù)看起來就是完全任意的順序。它通常是基于隱含索引中的順序形成的,但是我已經(jīng)學(xué)會(huì)甚至連經(jīng)驗(yàn)法則也不相信了——尤其是如果該查詢 在多個(gè)表之間執(zhí)行“JOIN”或者一些其它聚合函數(shù)。

            數(shù)據(jù)是按什么順序?qū)С龅耐ǔ2⒉恢匾菙?shù)據(jù)以什么順序?qū)胧欠浅jP(guān)鍵的。如果你使用的數(shù)據(jù)庫(kù)是后來導(dǎo)入行的正確性決定于早先存在的行,而且你是批量導(dǎo)入數(shù)據(jù)的話,那么導(dǎo)出的順序就很重要,你需要相應(yīng)地建立你的BCP語(yǔ)句。這一點(diǎn)似乎顯而易見,但是我經(jīng)常驚訝有那么多人,甚至包括一些資深的SQL Server專家都沒有意識(shí)到這一點(diǎn)。

            3、從BCP激活的存儲(chǔ)過程不能接收參數(shù)

            如果你使用帶有參數(shù)的存儲(chǔ)過程,作為BCP動(dòng)作Transact-SQL(T-SQL)語(yǔ)句的一部分,幾乎可以肯定它不能用,而且會(huì)在命令行拋出函數(shù)順序錯(cuò)誤。

            當(dāng)T-SQL語(yǔ)句傳遞給BCP時(shí),它將被使用“SET FMTONLY ON”機(jī)制進(jìn)行分析,來判斷結(jié)果集的柱狀格式。這意味著動(dòng)態(tài)構(gòu)造語(yǔ)句(比如帶參數(shù)的存儲(chǔ)過程)將不能正確分析,而且也不能在BCP下編譯。

            如果你想解決這個(gè)問題,有幾種方法可以選擇:

            創(chuàng)建不帶任何參數(shù)的存儲(chǔ)過程,用問號(hào)激活存儲(chǔ)過程并傳入需要的參數(shù)(可能通過數(shù)據(jù)源而不是命令行接收參數(shù))。

            用sqlcmd替代BCP。

             MSDN博客中提到了一個(gè)處理技巧,需要使用稱為“openrowset”的技巧。如果你通過“OPENROWSET ”函數(shù)運(yùn)行“SELECT”,你可以以臨時(shí)方式傳遞一個(gè)T-SQL語(yǔ)句,從而解決調(diào)用帶參數(shù)存儲(chǔ)過程的限制。然而,這種處理技巧也有局限:例如,與語(yǔ)句連 接時(shí)不應(yīng)該使用,因?yàn)檫\(yùn)行會(huì)對(duì)數(shù)據(jù)庫(kù)造成消極變化,而且該語(yǔ)句可能需要運(yùn)行不止一次。

            4、導(dǎo)入時(shí)要注意表定義

            當(dāng)你使用BCP從一個(gè)SQL Server源導(dǎo)出數(shù)據(jù),并導(dǎo)入到另一個(gè)SQL Server時(shí),你導(dǎo)出時(shí)的列定義和導(dǎo)入時(shí)的列定義必須相匹配。這也包括諸如NULL或者NOT NULL這類定義,在目標(biāo)表缺少它們會(huì)引起靜默數(shù)據(jù)損壞。

            5、在目標(biāo)數(shù)據(jù)庫(kù)上的觸發(fā)器不能被BCP觸發(fā)

            不管什么時(shí)候運(yùn)行導(dǎo)入操作,BCP的本地行為在目標(biāo)數(shù)據(jù)庫(kù)上都會(huì)禁用觸發(fā)器。因?yàn)锽CP導(dǎo)入操作通常很大,如果按默認(rèn)啟用觸發(fā)器的話,導(dǎo)入操作會(huì)很混亂。因此,你需要在BCP上使用命令選項(xiàng)“-h FIRE_TRIGGERS”,這樣觸發(fā)器才會(huì)被觸發(fā)。

             要注意,當(dāng)選項(xiàng)啟用時(shí),觸發(fā)器會(huì)為每個(gè)批量操作運(yùn)行一次,——也就是說,每次你運(yùn)行BCP時(shí)執(zhí)行一次。另外還要注意,在SQL Server 2005和以后的版本中,觸發(fā)器使用了“行版本”,在導(dǎo)入操作時(shí)用tempdb來存儲(chǔ)行版本信息。如果你的tempdb不能容納觸發(fā)器生成的大量數(shù)據(jù)涌 入,該操作將異常終止。

            6、BCP不能給本地附加文件輸出

            如果你使用BCP導(dǎo)出數(shù)據(jù)到文件,該文件必須是新創(chuàng)建的。你不能選擇現(xiàn)存文件,并把導(dǎo)出結(jié)果追加到文件。幸運(yùn)的是,解決辦法并不困難,您可以簡(jiǎn)單地導(dǎo)出到任何多個(gè)文件,然后使用COPY命令來整合這些結(jié)果。命令如下:

            COPY export1.dat + export2.dat export.dat

          posted on 2012-07-04 09:50 順其自然EVO 閱讀(352) 評(píng)論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫(kù)

          <2012年7月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 临漳县| 乌鲁木齐县| 三亚市| 丰原市| 华池县| 菏泽市| 寻甸| 甘肃省| 安福县| 阿图什市| 长沙市| 冕宁县| 大化| 安西县| 伊吾县| 长岛县| 赤壁市| 恩施市| 文登市| 抚州市| 张家口市| 土默特右旗| 双柏县| 专栏| 巧家县| 通许县| 大宁县| 定安县| 新干县| 贵南县| 汉寿县| 共和县| 霍林郭勒市| 邯郸市| 桑植县| 嘉禾县| 德昌县| 洛浦县| 梅河口市| 滨州市| 濉溪县|