求助:无法使用bcp命令行将竖线分隔文件导入临时表
解决BCP加载数据到全局临时表的问题
先给你揪出一个明显的小问题:你的BCP命令里重复用了-t参数——一次是-t "|"指定竖线分隔符,后面又加了个单独的-t,这会让BCP参数解析出错,这大概率是加载失败的直接原因之一,先把这个重复的-t删掉,只保留-t "|"就行。
接下来聊聊核心问题:为啥普通表能加载,全局临时表不行?因为你用xp_cmdshell执行BCP的时候,BCP会启动一个独立进程,并且新建一个SQL Server连接会话。虽说全局临时表是跨会话可见的,但这里有两个坑:
- SQL Server会给全局临时表自动加后缀(比如
##test会变成##test_xxxxxx),BCP用原始名称tempdb..##test根本找不到实际的表对象; xp_cmdshell运行的服务账户,说不定对这个全局临时表的访问权限不够。
结合你要临时处理数据(加列、导出再进最终表)的需求,给你两个实用的解决方案:
方案一:用TempDB里的普通表代替全局临时表
直接在TempDB里建一个普通表(不是临时表),这样BCP能正常访问,而且TempDB重启后会自动清空,完全符合临时处理的需求:
- 先建表:
CREATE TABLE tempdb.dbo.test_load (test1 int, test2 int, test3 int);
- 修正BCP命令并执行:
DECLARE @CMD NVARCHAR(MAX); SET @CMD = 'BCP "tempdb.dbo.test_load" IN "' + @sourcefoler + @filename + '" -S ' + @servername + ' -t "|" -c -F 2'; EXECUTE master..xp_cmdshell @CMD;
- 处理你的数据(加列啥的):
ALTER TABLE tempdb.dbo.test_load ADD new_column VARCHAR(50); -- 这里写你的其他数据处理逻辑
- 导出数据后记得删掉这个临时表:
-- 导出完成后执行 DROP TABLE tempdb.dbo.test_load;
方案二:用BULK INSERT替代BCP(不用折腾xp_cmdshell跨会话)
如果你的环境允许用BULK INSERT,直接在当前会话里把数据加载到全局临时表就行,完全避开跨会话的问题:
CREATE TABLE tempdb..##test (test1 int, test2 int, test3 int); BULK INSERT tempdb..##test FROM ''' + @sourcefoler + @filename + ''' WITH ( FIELDTERMINATOR = ''|'', ROWTERMINATOR = ''\n'', FIRSTROW = 2, CODEPAGE = ''RAW'' ); -- 给临时表加列并处理数据 ALTER TABLE tempdb..##test ADD new_column VARCHAR(50); -- 这里写你的数据处理逻辑 -- 导出数据到新文件(还是可以用BCP) DECLARE @exportCMD NVARCHAR(MAX); SET @exportCMD = 'BCP "SELECT * FROM tempdb..##test" OUT "C:\path\to\new_file.txt" -S ' + @servername + ' -t "|" -c'; EXECUTE master..xp_cmdshell @exportCMD; -- 最后清理临时表 DROP TABLE tempdb..##test;
提醒一下:不管用哪种方式,SQL Server的服务账户都需要有读取源文件、写入目标文件的权限哦。
内容的提问来源于stack exchange,提问作者Amitesh
相关产品推荐
相关产品推荐

