Sql-Server

在 SQL Server 中,是否還有其他數據導入和導出選項

  • November 11, 2015

我從 SQL Server 7 開始就一直在使用 SQL Server。所以我知道 BCP、批量插入、openrowset 和 SSIS。

我的問題很簡單:

  • 您是否知道使用 SQL Server Express 版本 SQL 2005 到 2014(以及即將推出的 2016)導入/導出數據的任何其他方法。

我想確保沒有其他任何東西,因為使用 BCP(這是我現在正在使用的)需要使用,xp_cmdshell並且出於安全原因,需要一個xp_cmdshell_proxy帳戶。我在工作中遇到了挑戰,我想確保沒有其他東西存在,或者在我回復之前這是 Microsoft SQL Server (Express) 中的新內容。

SQLCMD 可用於導出數據。預設輸出有時難以處理,但您可以使用一些命令行選項來關閉標題、修剪尾隨空格以及使用逗號分隔符而不是預設空格:

sqlcmd -Q "SET NOCOUNT ON; SELECT TOP(10) name, object_id, type FROM sys.objects;" ^
 -h-1 -W -s ","

回報:

sysrscols,3,S
sysrowsets,5,S
sysclones,6,S
sysallocunits,7,S
sysfiles1,8,S
sysseobjvalues,9,S
syspriorities,17,S
sysdbfrag,18,S
sysfgfrag,19,S
sysdbfiles,20,S

使用該-o選項將輸出發送到文件:

sqlcmd -Q "SET NOCOUNT ON; SELECT TOP(10) name, object_id, type FROM sys.objects;" ^
 -h-1 -W -s "," -o C:\temp\SysObjects.txt

可以創建自定義 .NET 程序(控制台應用程序、Windows 應用程序,甚至 Web 應用程序)來導入和/或導出。對於導入,由於此處不提供表值參數 (TVP),因此有時將數據轉換/序列化為 XML 會更快,然後執行將接受 XML 參數並使用該.nodes()函式的儲存過程,將其反序列化到可以通過INSERT INTO table (fields) SELECT x.value(),... FROM @XmlParam.nodes();構造插入的行中。當然,您不希望以這種方式處理 100 萬行,因此您會將導入文件分成 X 行的批次並一次發送 100 - 500 行。如果有很多數據,那麼直接語句可能會更好,但在這種情況下,您可能希望使用SqlTransactionINSERT將每批 X 行包裝到顯式事務中。


根據您(或與您一起工作的人)對 .NET 程式的熟悉程度,您可以使用 SQLCLR 建構您自己的自定義導入和/或導出功能。這適用於從 SQL Server 2005 開始的所有版本的所有 SQL Server 版本。

沿著這些構想,有一個商業可用的 SQLCLR 函式和過程庫,稱為SQL#(我是它的創建者)。一些函式和儲存過程處理數據的導入和導出。File_SplitIntoFields儲存過程返回一個結果集,其中每一行是輸入文件中的一行,但文件中的每個欄位是一個單獨的列**。**預設情況下,每個欄位的數據類型是NVARCHAR(MAX),但是有一個可選的輸入參數來指定每列的確切數據類型應該是什麼。這使得它很容易做到:

INSERT INTO dbo.MyImportTable (Col1, Col2, Col3, Col4)
 EXEC SQL#.File_SplitIntoFields
   @FilePath = N'',
   @RegExDelimiter = N',',
   @DataTypes = N'NVARCHAR(100),INT,DATETIME,BIT';

還有一個等效的儲存過程,稱為INET_SplitIntoFields,它做同樣的事情,但不是從文件中獲取數據,而是直接從 URL 流式傳輸數據(因此無需先在本地下載文件)。

對於導出,有一個名為DB_BulkExport的儲存過程,它結合了 SQLCMD 和 SSIS 的許多功能。我在需要進行多次導出並且無法在 SQLCMD 和 SSIS 之間做出決定之後創建了它,因為每個都有其優點和缺點,並且每個都有一個或兩個另一個沒有的功能,但所有這些功能都是需要。例如,DB_BulkExport不需要任何硬編碼的輸出欄位規範,並且可以處理SELECT *查詢(我不知道如何在 SSIS 中管理,但使用 SQLCMD 很容易)。它還可以處理欄位的文本限定,而無需更新源查詢以連接其中的雙引號(這使得查詢非常難看且難以維護)。事實上,它可以設置為文本限定所有欄位,或者只是根據其數據類型(字元串、日期、GUID 等)需要它的欄位。

引用自:https://dba.stackexchange.com/questions/120661