【发布时间】:2020-06-21 16:31:08
【问题描述】:
我可以在本地 SQL Server 机器上运行以下命令而不会出现任何问题:
exec sp_configure 'show advanced options', 1
reconfigure
go
exec sp_configure 'Ad Hoc Distributed Queries', 1
reconfigure
go
exec LoadData 'C:\MyDataFile.urg';
go
但是当我尝试在 Azure SQL 上运行 SP_CONFIGURE 命令时,我收到以下错误:
此版本的 SQL Server 不支持语句“CONFIG”。
当我执行加载数据命令时,出现以下错误
无法批量加载,因为文件 C:\MyDataFile.urg" 无法打开。操作系统错误代码 (null)。
上述错误是有道理的,因为我试图从 Azure 云访问我本地计算机上的文件。是否有一个等效的加载数据的过程,我可以在 Azure 中遵循以转储文件的内容?
我可以将文件放在 Azure blob 中,但是我执行的命令类似于加载数据?
-- 更新 1 回答时请注意两点 1) 我正在使用以 .urg 结尾且不是 csv 文件的第三方文件。
2) 当我使用 exec LoadData 'C:\MyDataFile.urg';请注意,我没有使用文件数据所在的表名。 LoadData 命令执行文件并将数据转储到各自的文件中。我假设 .urg 文件被打开并执行,并且其中包含命令以了解哪些数据在哪里。
--更新2 所以我的理解是不正确的。发现 LoadData 是第三方正在使用的存储过程,它采用这样的文件路径。磁盘上的文件很好用,我需要将其发送到 azure storage blob path。
CREATE PROCEDURE [dbo].[LoadData]
@DataFile NVARCHAR(MAX)
AS
DECLARE @LoadSql NVARCHAR(MAX)
SET @LoadSql = '
BULK INSERT UrgLoad FROM ''' + @DataFile + '''
WITH (
FIRSTROW = 2,
FIELDTERMINATOR = ''~'',
ROWTERMINATOR = ''0x0a'',
KEEPNULLS,
CODEPAGE = ''ACP''
)
'
EXEC sp_executesql @LoadSql
SELECT @Err = @@ERROR
现在我需要找到一种方法来将 Azure 存储 blob 路径发送到此存储过程,以便它可以打开它。如果我遇到问题,我会更新。
--更新3 由于我的 blob 存储帐户不是公开的,我确定我需要添加授权块。我将这段代码添加到 proc
CREATE DATABASE SCOPED CREDENTIAL MyAzureBlobStorageCredential
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = 'sp=r&st=2020-03-10T01:04:16Z&se=2020-03-10T09:04:16Z&spr=https&sv=2019-02-02&sr=b&sig=Udxa%2FvPrUBZt09GAH4YgWd9joTlyxYDC%2Bt7j7CmuhvQ%3D';
-- Create external data source with the URL of the Blob storage Account and associated credential since its not public
CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE,
LOCATION = 'https://dev.blob.core.windows.net/urg',
CREDENTIAL= MyAzureBlobStorageCredential
);
当我执行 proc 时说它已经存在。
Msg 15530, Level 16, State 1, Procedure LoadData, Line 14 [Batch Start Line 1]
The credential with name "MyAzureBlobStorageCredential" already exists.
Msg 46502, Level 16, State 1, Procedure LoadData, Line 27 [Batch Start Line 1]
Type with name 'MyAzureBlobStorage' already exists.
当我取出它并像这样更新批量插入代码时
DECLARE @LoadSql NVARCHAR(MAX)
SET @LoadSql = '
BULK INSERT UrjanetLoad FROM ''' + @DataFile + '''
WITH ( DATA_SOURCE = ''MyAzureBlobStorage'',
FIRSTROW = 2,
FIELDTERMINATOR = ''~'',
ROWTERMINATOR = ''0x0a'',
KEEPNULLS,
CODEPAGE = ''ACP''
)
'
但它告诉我
Cannot bulk load because the file "https://dev.blob.core.windows.net/urg/03_06_20_16_23.urg" could not be opened. Operating system error code 5(Access is denied.).
我想问题是我在授权过程中遗漏了什么,我怎样才能使它成为我猜想的存储过程的一部分,所以每当它运行时,它都会选择它。
更新 4:本文帮助使用凭据从 blob 存储访问文件,删除外部数据源和范围凭据,并在存储过程中获取新的 SAS 令牌,以防它可以帮助其他人`https://social.technet.microsoft.com/wiki/contents/articles/52061.t-sql-bulk-insert-azure-csv-blob-into-azure-sql-database.aspx
现在我遇到错误
Cannot bulk load because the file "03_06_20_16_23.urg" could not be opened. Operating system error code 32(The process cannot access the file because it is being used by another process.).
试过这篇文章,但没有解决文件正在被另一个进程使用的问题。
更新 5:这是 proc 的样子
alter PROCEDURE [dbo].[TestLoad]
@DataFile NVARCHAR(MAX), @SAS_Token VARCHAR(MAX),@Location VARCHAR(MAX)
AS
BEGIN TRAN
-- Turn on NOCOUNT to prevent message spamming
SET NOCOUNT ON;
DECLARE @CrtDSSQL NVARCHAR(MAX), @DrpDSSQL NVARCHAR(MAX), @ExtlDS SYSNAME, @DBCred SYSNAME, @BulkInsSQL NVARCHAR(MAX) ;
SELECT @ExtlDS = 'MyAzureBlobStorage'
SELECT @DBCred = 'MyAzureBlobStorageCredential'
SET @DrpDSSQL = N'
IF EXISTS ( SELECT 1 FROM sys.external_data_sources WHERE Name = ''' + @ExtlDS + ''' )
BEGIN
DROP EXTERNAL DATA SOURCE ' + @ExtlDS + ' ;
END;
IF EXISTS ( SELECT 1 FROM sys.database_scoped_credentials WHERE Name = ''' + @DBCred + ''' )
BEGIN
DROP DATABASE SCOPED CREDENTIAL ' + @DBCred + ';
END;
';
SET @CrtDSSQL = @DrpDSSQL + N'
CREATE DATABASE SCOPED CREDENTIAL ' + @DBCred + '
WITH IDENTITY = ''SHARED ACCESS SIGNATURE'',
SECRET = ''' + @SAS_Token + ''';
CREATE EXTERNAL DATA SOURCE ' + @ExtlDS + '
WITH (
TYPE = BLOB_STORAGE,
LOCATION = ''' + @Location + ''' ,
CREDENTIAL = ' + @DBCred + '
);
';
-- PRINT @CrtDSSQL
EXEC (@CrtDSSQL);
-- Set up the load timestamp
DECLARE @LoadTime DATETIME, @Err varchar(60)
SELECT @LoadTime = GETDATE()
-- Set the bulk load command to a string and execute with sp_executesql.
-- This is the only way to do parameterized bulk loads
DECLARE @LoadSql NVARCHAR(MAX)
SET @LoadSql = '
BULK INSERT TestLoadTable FROM ''' + @DataFile + '''
WITH ( DATA_SOURCE = ''MyAzureBlobStorage'',
FIRSTROW = 2,
FIELDTERMINATOR = ''~'',
ROWTERMINATOR = ''0x0a'',
KEEPNULLS,
CODEPAGE = ''ACP''
)
'
EXEC (@LoadSql);
--EXEC sp_executesql @LoadSql
SELECT @Err = @@ERROR
IF @Err <> 0 BEGIN
PRINT 'Errors with data file ... aborting'
ROLLBACK
RETURN -1
END
SET NOCOUNT OFF;
COMMIT
GO
这就是我试图称呼它的方式。
EXEC TestLoad 'TestFile.csv',
'sv=2019-02-02&ss=bfqt&srt=sco&sp=rwdlacup&se=2020-03-16T02:07:03Z&st=2020-03-10T18:07:03Z&spr=https&sig=TleUPwAyEVT6dzX17fH6rq1lQQRAhIRImDHdJRKIrKE%3D',
''https://dev.blob.core.windows.net/urg';
这是错误
Cannot bulk load because the file "TestFile.csv" could not be opened. Operating system error code 32(The process cannot access the file because it is being used by another process.).
Errors with data file ... aborting
【问题讨论】:
标签: azure azure-sql-database azure-storage