BCP导出动态创建的全局临时表失败,请求排查问题
问题原因与解决办法
核心原因
通过SELECT ... INTO创建的全局临时表,SQL Server在tempdb中生成的元数据对象状态,和显式CREATE TABLE创建的临时表存在差异。BCP工具在读取这类临时表的元数据时,会触发内部断言错误(即你遇到的Assertion failed: 0 == m_event),导致命令卡住甚至崩溃。
本质上这是BCP工具与SELECT INTO创建临时表的元数据处理逻辑不兼容的问题,属于SQL Server工具链的已知兼容性限制。
可行解决方案
方案1:显式创建全局临时表,再插入数据
放弃SELECT INTO,改用先创建表结构,再用INSERT INTO ... SELECT导入数据,这样生成的临时表元数据符合BCP的预期:
IF OBJECT_Id('tempdb..##TmpTable1') IS NOT NULL BEGIN DROP TABLE ##TmpTable1 END GO CREATE TABLE ##TmpTable1(Id int, Val varchar(100)) -- 需与原SELECT查询的列类型匹配 GO INSERT INTO ##TmpTable1(Id,Val) SELECT Id,Val FROM Table1 GO
之后执行BCP命令即可正常工作:
bcp tempdb.##TmpTable1 format nul -c -t"|" -f "C:\TmpTable1.fmt" -S MyDBServerName -T bcp tempdb.##TmpTable1 OUT "C:\TmpTable1.out" -c -t"|" -S MyDBServerName -T
方案2:先写入本地临时表,再转存全局临时表
如果必须使用SELECT INTO,可以先创建本地临时表,再将数据复制到全局临时表:
IF OBJECT_Id('tempdb..##TmpTable1') IS NOT NULL BEGIN DROP TABLE ##TmpTable1 END GO SELECT Id,Val INTO #LocalTmp FROM Table1 GO CREATE TABLE ##TmpTable1(Id int, Val varchar(100)) GO INSERT INTO ##TmpTable1(Id,Val) SELECT Id,Val FROM #LocalTmp GO DROP TABLE #LocalTmp GO
后续BCP命令可正常执行。
额外注意事项
- 执行完
SELECT INTO后,务必确保当前会话没有持有临时表的排他锁,可通过执行GO或显式COMMIT(若在事务中)释放锁,避免BCP访问时被阻塞。 - 若使用较旧版本的SQL Server/BCP工具,升级到最新补丁版本可能缓解这类元数据处理的bug。
内容的提问来源于stack exchange,提问作者Tech Sawy
相关产品推荐
相关产品推荐

