如何高效批量将本地表数据插入SQL Server链接服务器?
问题描述
我需要将本地SQL Server表的数据插入自建的SQL Server链接服务器(目标为Parallel DataWarehousing)中的表,遇到以下问题:
- 可正常查询链接服务器表,连接无问题:
SELECT TOP 100 * FROM [LinkedServerName].[database].[Schema].[table] - 直接执行INSERT语句报错:
INSERT INTO [LinkedServerName].[database].[Schema].[table] (row1, row2) VALUES (value1, value2)错误信息:Cursor support is not an implemented feature for SQL Server Parallel DataWarehousing TDS endpoint.
- 使用
EXEC() AT单条插入成功,但数据量大时逐条插入效率极低:EXEC ('INSERT INTO [database].[Schema].[table] (row1, row2) VALUES (value1, value2)') AT [LinkedServerName] - 尝试在
EXEC() AT中引用本地表时提示表不存在:EXEC ('INSERT INTO [database].[Schema].[table] (row1, row2) SELECT r1,r2 form [mylocalserver].[database].[Schema].[table]') AT [LinkedServerName]错误信息:[mylocalserver].[database].[Schema].[table] doesn't exist LinkedServer.
- 使用
OPENQUERY插入也报相同游标错误:insert into openquery([LinkedServerName],'Select row1, row2 from [database].[Schema].[table]' ) select r1, r2 from [mylocalserver].[database].[Schema].[table]错误信息:Cursor support is not an implemented feature for SQL Server Parallel DataWarehousing TDS endpoint.
请问如何解决该问题,实现高效批量插入?
解决方案
1. 用bcp命令行工具批量导入(最高效)
PDW原生支持bcp,这是批量加载最快的方式,步骤如下:
- 先把本地表数据导出为CSV文件:
bcp "[mylocalserver].[database].[Schema].[source_table]" out "C:\temp\data_batch.csv" -S mylocalserver -d database -U your_username -P your_password -c -t "," -r "\n" - 再把CSV文件加载到PDW的目标表:
bcp "[database].[Schema].[target_table]" in "C:\temp\data_batch.csv" -S LinkedServerName -d database -U pdw_username -P pdw_password -c -t "," -r "\n" -b 10000-b 10000代表每10000条数据提交一次,可根据服务器性能调整数值。
2. 让PDW主动拉取本地数据(避免游标触发)
通过在PDW端执行OPENROWSET拉取本地数据,跳过本地的游标操作逻辑:
EXEC ('INSERT INTO [database].[Schema].[target_table] (row1, row2) SELECT r1, r2 FROM OPENROWSET(''SQLNCLI'', ''Server=mylocalserver;Trusted_Connection=yes;'', ''SELECT r1, r2 FROM [database].[Schema].[source_table]'')') AT [LinkedServerName]
注意:需要先在本地服务器开启Ad Hoc Distributed Queries配置:
sp_configure 'show advanced options', 1; RECONFIGURE; sp_configure 'Ad Hoc Distributed Queries', 1; RECONFIGURE;
同时要保证PDW服务器能直接访问本地SQL Server的端口(默认1433)。
3. 用表值参数(TVP)批量插入
通过表值参数一次性传递批量数据,减少网络交互:
- 先在PDW上创建对应的表类型:
EXEC ('CREATE TYPE [Schema].[BatchTableType] AS TABLE (row1 INT, row2 VARCHAR(50))') AT [LinkedServerName] - 本地也要创建完全同名同结构的表类型,然后声明表变量并填充数据:
CREATE TYPE [Schema].[BatchTableType] AS TABLE (row1 INT, row2 VARCHAR(50)); GO DECLARE @LocalBatchData [Schema].[BatchTableType]; INSERT INTO @LocalBatchData (row1, row2) SELECT r1, r2 FROM [mylocalserver].[database].[Schema].[source_table]; - 最后通过EXEC() AT传递表值参数批量插入:
EXEC ('INSERT INTO [database].[Schema].[target_table] (row1, row2) SELECT row1, row2 FROM ?') AT [LinkedServerName] WITH PARAMETERS (@LocalBatchData READONLY);
4. 用SSIS包实现批量加载
如果需要处理复杂的ETL逻辑(比如数据清洗、增量同步),可以用SSIS:
- 创建SSIS包,配置本地SQL Server为数据源,PDW为目标数据源;
- 使用OLE DB Destination组件,启用批量插入模式,SSIS会自动适配PDW的特性,避免游标问题,同时支持并行加载优化性能。
内容的提问来源于stack exchange,提问作者kevin
相关产品推荐
相关产品推荐

