sql-server - Azure SQL 数据库 - 在存储过程中获取文件内容的正确方法

标签 sql-server azure stored-procedures azure-sql-database sql-server-2017

** 场景:**

  • SQL 存储过程将文件名作为输入。
  • 读取文件内容并将其插入表中。

对于本地SQL Server,上述场景是通过以下存储过程实现的。

-- @_filePath would be input to the store procedure
DECLARE @_filePath NVARCHAR(MAX) =  'C:\SQLContent\test1.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 Server,SQL Server 无法访问上述存储过程中提供的路径。

C:\SQLContent\test1.sql

SQL Azure 错误消息:

Cannot bulk load because the file "C:\SQLContent\test1.sql" could not be opened. Operating system error code (null).

可能的解决方案:

  1. 将文件 test1.sql 上传到 Azure blob,并在存储过程中从 blob 读取文件内容,如下所示:
select *
from OPENROWSET
 (BULK 'temp1.sql', DATA_SOURCE = 'MyAzureStorage', SINGLE_CLOB) as data

引用 - [error executing OPENROWSET (BULK) / Azure SQL Database

  • 不要将 @_filePath 作为参数传递给存储过程,而是将文件内容作为参数传递给存储过程。
  • 询问

    在解决该问题的两种可能的解决方案中,哪一种是最好的,为什么?

    另外,建议是否还有其他更好的方法。

    最佳答案

    您可以使用 OPENROWSET,也可以使用 BULK INSERT。我不知道有什么优点或缺点可以使一个人比另一个人更好。但是,如果存储帐户是公共(public)的,您至少需要创建一个外部数据源:

    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');
    

    希望这有帮助。

    关于sql-server - Azure SQL 数据库 - 在存储过程中获取文件内容的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52420528/

    相关文章:

    sql-server - SQL Server 触发器问题

    SQL 查询获取给定邮政编码 20 英里半径内的所有邮政编码(地址)

    sql-server - 通过数据库链接将 Oracle 连接到 SQL Server

    mysql - 我可以在存储过程中使用 mysqlimport/LOAD DATA LOCAL INFILE

    stored-procedures - SQL Server的存储过程的隔离级别?

    oracle - 如何使用 MyBatis 将 Java 对象列表传递给 Oracle 存储过程?

    SQL - 如何跨行转换和合并数据

    asp.net-mvc-3 - 执行代码优先迁移在发布设置中显示为灰色

    .net - Windows Server 重新启动后未启动

    azure - 访问 Azure Devops 预定义变量中的 github 用户名