本文原創,轉載請標明出處
BCP 工具的使用
The bulk copy program utility (bcp) bulk copies data between an instance of Microsoft SQL Server and a data file in a user-specified format. The bcp utility can be used to import large numbers of new rows into SQL Server tables or to export data out of tables into data files. Except when used with the queryout option, the utility requires no knowledge of Tranuserct-SQL. To import data into a table, you must either use a format file created for that table or understand the structure of the table and the types of data that are valid for its columns.
大容量復制程序實用工具 (bcp) 可以在 Microsoft SQL Server 實例和用戶指定格式的數據文件間大容量復制數據。使用 bcp 實用工具可以將大量新行導入 SQL Server 表,或將表數據導出到數據文件。 除非與 queryout 選項一起使用,否則使用該實用工具不需要了解 Tranuserct-SQL知識。 若要將數據導入表中,必須使用為該表創建的格式文件,或者必須了解表的結構以及對於該表中的列有效的數據類型。
如果使用 bcp 備份數據,請創建一個格式化文件來記錄數據格式。 bcp 數據文件 不包括 任何架構或格式信息,因此如果已刪除表或視圖並且不具備格式化文件,則可能無法導入數據。
版本信息
我們打開CMD命令 輸入 CMD –v 就可以看到BCP是否安裝以及其版本
我們在這里使用的是SQL server 2008 R2自帶的版本,目前最新的是基於SQL server 2017 的14.0版本。最新版本支持對微軟虛擬機上的數據庫進行操作
基本語法
數據文件
數據文件的完整路徑。 將數據批量導入 SQL Server時,數據文件將包含要復制到指定的表或視圖中的數據。 從SQL Server中批量導出數據時,數據文件將包含從表或視圖中復制的數據。 路徑可以有 1 到 255 個字符。 數據文件最多可包含 2^63 - 1 行。
dbtable
指定的表或視圖所在數據庫的名稱。 如果未指定,則使用用戶的默認數據庫。
你也可以使用 d- 顯式指定數據庫名稱。
in | out | queryout | format nul
指定大容量復制的方向,具體如下:
- in 從文件復制到數據庫表或視圖。
- out 從數據庫表或視圖復制到文件。 如果指定了現有文件,則該文件將被覆蓋。 提取數據時,請注意 bcp 實用工具將空字符串表示為 null,而將 null 字符串表示為空字符串。
- queryout 從查詢中復制,僅當從查詢大容量復制數據時才必須指定此選項。
- format 根據指定的選項(-n、 -c、 -w或 -N)以及表或視圖的分隔符創建格式化文件。 大容量復制數據時, bcp 命令可以引用一個格式化文件,從而避免以交互方式重復輸入格式信息。 format 選項要求指定 -f選項;創建 XML 格式化文件時還需要指定 -x 選項。 有關詳細信息,請參閱 創建格式化文件 (SQL Server)。必須將 null 指定為值 (format nul)。
owner
表或視圖的所有者的名稱。 如果執行該操作的用戶擁有指定的表或視圖,則owner 是可選的。 如果未指定owner ,並且執行該操作的用戶不是指定的表或視圖的所有者,則 SQL Server 將返回錯誤消息,而且該操作將取消。
Note:
" query " 是一個返回結果集的 Tranuserct-SQL 查詢。 如果該查詢返回多個結果集,則只將第一個結果集復制到數據文件,而忽略其余的結果集。 將查詢用雙引號括起來,將查詢中嵌入的任何內容用單引號括起來。 從查詢大容量復制數據時,也必須指定。queryout 。
只要在執行 bcp 語句之前存儲過程內引用的所有表均存在,查詢就可以引用該存儲過程。 例如,如果存儲過程生成一個臨時表,則 bcp 語句便會失敗,因為該臨時表只在運行時可用,而在語句執行時不可用。 在這種情況下,應考慮將存儲過程的結果插入表中,然后使用 bcp 將數據從表復制到數據文件中。
數據導出
導出特定表
從數據庫中導出一張表的所有內容:
我們輸入命令:
bcp [tablename] out C:\report.txt -S localhost\DATABASE-U user -P password
BCP會要求我們輸入到處字段的數據類型,使用這種方式依次輸出,會耗費我們大量的時間,實際上我們可以使用代碼頁,取消類型的輸入操作。命令如下:
bcp wggc.dbo.afp_reportinfo out –c –T C:\report.txt -S localhost\DATABASE-U user -P password
我們看到工具耗時 164秒導出了 1583613條記錄,每秒可以處理9623條記錄。速度還是比較快速的。導出的txt文件大小為549M, 數據文件較大。
需要注意的是, bcp 實用工具將空字符串表示為 null,而將 null 字符串表示為空字符串。
導出查詢語句
我們還可以使用查詢語句讀取我們需要的語句,並導出。
bcp "select top 10 * from wggc.dbo.AFP_ReportInfo where CreatedTime >'2016-08-18 15:51:48.497'" queryout C:\test.txt -c -E -k -T -S localhost\DATABASE-U user -P password
導出存儲過程
我們還可以使用執行存儲過程,然后獲取我們所需的數據導出,需要注意的是,如果存儲過程中存在臨時表,那么導出操作將不能正常運行。因為命令是去獲取表中的信息,無法獲取內存空間中的臨時數據。
我們新建一個存儲過程:
USE [WGGC]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
Create PROCEDURE [dbo].BCPTest
AS
BEGIN
select top 10 * from wggc.dbo.AFP_ReportInfo where CreatedTime >'2016-08-18 15:51:48.497'
END
使用以下命令可以將數據導出
bcp "exec wggc.dbo.BCPTest" queryout C:\test.txt -c -E -k -T -S localhost\DATABASE-U user -P password
數據導入操作:
使用BCP導入
數據導入操作基本語法和導出相類似,需要須改out to in,例如:
bcp wggc.dbo.afp_reportinfo in "C:\ test.txt" -c -E -k –T -S localhost\DATABASE-U user -P password
大家要注意參數 –E –k的使用
-E:表示保留標識符,使用該參數的話,導入的時候會保留原有的標識符,而不會自增長。
-k:表示保留null值,使用該參數,在導入的時候不會將null導入成空字符。
建議使用-o + 文件路徑將導入的過程,以日志的形式將記錄保留下來
使用BCP導入的優勢在於快速,效率高,並且可以避開觸發器的相關問題。
使用BulkInsert SQL 語句導入
我們還可以使用SQL語句來導入我們已經備份好的數據文件:
如:
BULK INSERT wggc.dbo.afp_reportinfo
FROM "C:\ test.txt"
WITH
(
KEEPIDENTITY
)
Bulk insert的語法如下:
BULK INSERT [ [ 'database_name'.][ 'owner' ].]{ 'table_name' FROM 'data_file' }
WITH (
[ BATCHSIZE [ = batch_size ] ],
[ CHECK_CONSTRAINTS ],
[ CODEPAGE [ = 'ACP' | 'OEM' | 'RAW' | 'code_page' ] ],
[ DATAFILETYPE [ = 'char' | 'native'| 'widechar' | 'widenative' ] ],
[ FIELDTERMINATOR [ = 'field_terminator' ] ],
[ FIRSTROW [ = first_row ] ],
[ FIRE_TRIGGERS ],
[ FORMATFILE = 'format_file_path' ],
[ KEEPIDENTITY ],
[ KEEPNULLS ],
[ KILOBYTES_PER_BATCH [ = kilobytes_per_batch ] ],
[ LASTROW [ = last_row ] ],
[ MAXERRORS [ = max_errors ] ],
[ ORDER ( { column [ ASC | DESC ] } [ ,...n ] ) ],
[ ROWS_PER_BATCH [ = rows_per_batch ] ],
[ ROWTERMINATOR [ = 'row_terminator' ] ],
[ TABLOCK ],
)
詳細參數說明:請參閱微軟官網
Sample1 大批量數據導出導入
最后我們來看看使用BCP大批量導入數據的性能表現:
導出數據:
bcp wggc.dbo.afp_reportinfo out C:\report.txt -c -T -S localhost\DATABASE-U user -P password
刪除數據:
truncate table wggc.dbo.afp_reportinfo
導入數據:
bcp wggc.dbo.afp_reportinfo in "C:\report.txt" -c -E -k -T -S localhost\DATABASE-U user -P password
我們可以看到數據導入總共耗時549秒,平均每秒可以導入2884.91條數據,性能還是比較好的
Sample2 大批量數據導出導入工具
我個人使用autoit寫了一個工具,用於數據的導入導出操作,可以從\\10.184.129.235\puma\Team\Ralf\Tool\BCP_20180822_1805中獲取。
或者使用以下鏈接: https://github.com/wanghao4023030/MyWorkRelated/tree/master/AutoIT/BCP_Import_Export_tool
文件名分別為 Export and import, 該文件夾里面有一些基於1805的歷史數據,大家也可以直接使用。
我會逐步優化該工具,以滿足項目組的使用。
usermple3 BCP在項目中的使用
之前services team 反映升級過程過於緩慢,其中有部分時間是從film 和 report表中獲取信息,並插入到exam表中。我們可以使用BCP或者bulk insert的方式生成新的數據。我使用下列語句:
使用CTE建立子查詢, 收集film 和report 表中既有film和report的數據,並導入到新生成的exam表中。
1. 導出數據:bcp "exec wggc.dbo.BCPTest1" queryout C:\exzaminfo.txt -c -E –k -T -S localhost\DATABASE-U user -P password
其中film表數據190707條
其中report表數據1583612 條
總共導出數據 81655條,耗時677秒。大部分的時間耗費中數據查詢中:
2. 使用語句bcp wggc.dbo.AFP_Examinfo IN C:\exzaminfo.txt -c -E -k -T -S localhost\DATABASE-U user -P password
我們可以看到導入81655行花費8.8秒,速度非常快。