如何解决本地Azure Blob Storage向SQL Server执行BULK INSERT的报错?
从本地Blob存储模拟器导入文件到SQL Server的问题处理
场景描述
目标是配置本地SQL Server实例对接本地Azure Blob存储模拟器,通过BULK INSERT操作完成CSV文件导入,操作过程中返回报错:
Bad or inaccessible location specified in external data source "external_source".
即“指定位置无效或不可访问”。
已执行的配置流程
- 创建数据库主密钥
IF EXISTS (SELECT * FROM sys.symmetric_keys WHERE name = '##MS_DatabaseMasterKey##') DROP MASTER KEY; --Create Master Key CREATE MASTER KEY ENCRYPTION BY PASSWORD='MyStrongPassword';
- 创建数据库作用域凭据
-- DROP DB Credentials If Exist IF EXISTS (SELECT * FROM sys.database_credentials WHERE name = 'credentials') DROP DATABASE SCOPED CREDENTIAL credentials; --Create scoped credentials to connect to Blob CREATE DATABASE SCOPED CREDENTIAL credentials WITH IDENTITY = 'SHARED ACCESS SIGNATURE', SECRET = 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=='; --local storage key GO
- 创建Blob类型外部数据源
CREATE EXTERNAL DATA SOURCE external_source WITH ( TYPE = BLOB_STORAGE, LOCATION = 'http://127.0.0.1:10000/devstoreaccount1/container/some_folder/', CREDENTIAL = credentials )
- 执行批量导入语句
BULK INSERT [dbo].[StagingTable] FROM 'some_file_on_blob_storage.csv' WITH ( DATA_SOURCE = 'external_source', FIRSTROW = 1, FIELDTERMINATOR = ',', ROWTERMINATOR = '\n' )
可落地的修复步骤
- 修正凭据匹配规则
当前配置存在凭据字段不匹配的问题:当IDENTITY设为SHARED ACCESS SIGNATURE时,SECRET字段需要填写本地Blob容器生成的SAS令牌查询串(去掉开头的?,确保权限包含至少读取、列出内容的权限,有效期覆盖操作时段),不能直接填存储账号的主密钥。
如果使用的是早期版本的Blob模拟器,不支持SAS令牌签发,可直接把IDENTITY修改为SharedKey,SECRET字段填写本地存储账号的完整主密钥,和实际账号配置对齐。 - 调整外部数据源路径格式
SQL Server对BLOB_STORAGE类型的外部数据源有严格的路径要求:LOCATION必须精确到存储账号下的容器根路径,不能提前嵌套容器下的子文件夹层级。需要把原配置里的LOCATION调整为http://127.0.0.1:10000/devstoreaccount1/container/,原来放在LOCATION里的子文件夹路径some_folder/,直接拼接在BULK INSERT语句的文件路径位置即可,即把导入语句里的FROM路径修改为'some_folder/some_file_on_blob_storage.csv'。 - 补充连接配置适配本地HTTP服务
高版本SQL Server默认要求外部存储源使用HTTPS协议,对接本地HTTP协议的Blob模拟器时,需要在外部数据源定义里追加CONNECTION_OPTIONS = 'TrustServerCertificate=Yes'参数,跳过本地证书校验。 - 校验运行权限
确认SQL Server服务的运行账号具备访问127.0.0.1:10000端口的权限,不要仅通过本地客户端浏览器测试连通性就判定网络正常——SQL Server的请求是由后台服务进程发起的,和客户端的网络环境相互独立。如果SQL Server是容器化部署,不能用127.0.0.1作为模拟器地址,需要替换为宿主机在容器网络段内的可访问IP。
内容的提问来源于stack exchange,提问作者Dylan Smyth
相关产品推荐
相关产品推荐

