** 场景:**
- SQL 存储过程将文件名作为输入。
- 读取文件的内容并将其插入到表中。
对于本地 SQL 服务器,上述方案已通过以下存储过程实现。
-- @_filePath would be input to the store procedure
DECLARE @_filePath NVARCHAR(MAX) = 'C:SQLContenttest1.sql'
CREATE TABLE tmpTable (tmpIndex INT NOT NULL IDENTITY PRIMARY KEY CLUSTERED, sqlContent NVARCHAR(MAX) NOT NULL)
-- Read content of the file @_filePath
DECLARE @_insertQuery NVARCHAR(MAX) = 'insert tmpTable (sqlContent) select * from OPENROWSET(bulk ''' + @_filePath + ''', SINGLE_CLOB) as a'
EXEC sp_ExecuteSql @_insertQuery
Select * from tmpTable
问题:
实际问题在于 Azure SQL 服务器,SQL 服务器无法访问上述存储过程中提供的路径。
C:\SQLContent\test1.sql
SQL Azure 的错误消息:
无法大容量加载,因为无法打开文件"C:\SQLContent\test1.sql"。操作系统 错误代码(空)。
可能的解决方案:
- 将文件 test1.sql 上传到 Azure Blob,并在存储过程中从 Blob 读取文件内容,如下所示:
select * from OPENROWSET (BULK 'temp1.sql', DATA_SOURCE = 'MyAzureStorage', SINGLE_CLOB) as data
引用 - [执行 OPENROWSET (BULK)/Azure SQL 数据库时出错
- 不要将@_filePath作为参数传递给存储
- 过程,而是将文件内容作为参数传递给存储过程。
问
在问题的两种可能解决方案中,哪一种是最好的,为什么?
另外,建议是否有其他更好的方法。
您可以使用 OPENROWSET,也可以使用 BULK INSERT。我不知道有什么优点或缺点可以使一个比另一个更好。但是,如果存储帐户是公共帐户,则至少需要创建外部数据源:
CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE, LOCATION = 'https://myazureblobstorage.blob.core.windows.net');
BULK INSERT Product
FROM 'data/product.dat'
WITH ( DATA_SOURCE = 'MyAzureBlobStorageAccount');
如果存储帐户不是公共帐户,则需要另外创建数据库范围的凭据。
CREATE DATABASE SCOPED CREDENTIAL MyAzureBlobStorageCredential
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = 'sv=2015-12-11&ss=b&srt=sco&sp=rwac&se=2017-02-01T00:55:34Z&st=2016-12-29T16:55:34Z&spr=https&sig=copyFromAzurePortal';
CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE,
LOCATION = 'https://myazureblobstorage.blob.core.windows.net',
CREDENTIAL= MyAzureBlobStorageCredential);
BULK INSERT Product
FROM 'data/product.dat'
WITH ( DATA_SOURCE = 'MyAzureBlobStorageAccount');
希望这有帮助。